Существует ли разумный подход к параметрам типа "по умолчанию" в C# Generics?


в шаблонах C++ можно указать, что определенный параметр типа является значением по умолчанию. Т. е. если явно не указано, он будет использовать тип T.

можно ли это сделать или приблизить в C#?

Я ищу что-то вроде:

public class MyTemplate<T1, T2=string> {}

так что экземпляр типа, который явно не указать T2:

MyTemplate<int> t = new MyTemplate<int>();

было бы по существу:

MyTemplate<int, string> t = new MyTemplate<int, string>();

в конечном счете я смотрю на случай, когда есть шаблон, который является довольно широко используется, но я рассматриваю возможность расширения с дополнительным параметром типа. Я мог бы подкласс, я думаю, но мне было любопытно, если бы были другие варианты в этом ключе.

5 68

5 ответов:

подклассы-это лучший вариант.

Я бы подкласс вашего основного общего класса:

class BaseGeneric<T,U>

С определенным классом

class MyGeneric<T> : BaseGeneric<T, string>

Это позволяет легко сохранить вашу логику в одном месте (базовый класс), но также легко обеспечить оба варианта использования. В зависимости от класса, вероятно, очень мало дополнительной работы, необходимой для этого.

одно из решений-это подклассы. Другой, который я бы использовал вместо этого, - это заводские методы (в сочетании с ключевым словом var).

public class MyTemplate<T1,T2>
{
     public MyTemplate(..args..) { ... } // constructor
}

public static class MyTemplate{

     public static MyTemplate<T1,T2> Create<T1,T2>(..args..)
     {
         return new MyTemplate<T1, T2>(... params ...);
     }

     public static MyTemplate<T1, string> Create<T1>(...args...)
     {
         return new MyTemplate<T1, string>(... params ...);
     }
}

var val1 = MyTemplate.Create<int,decimal>();
var val2 = MyTemplate.Create<int>();

в приведенном выше примере val2 типа MyTemplate<int,string>, а не тип, производный от него.

тип class MyStringTemplate<T>:MyTemplate<T,string> - это не тот же тип, что MyTemplate<T,string>. Это может создать некоторые проблемы в определенных ситуациях. Например, вы не можете привести экземпляр MyTemplate<T,string> до MyStringTemplate<T>.

вы также можете создать перегрузку класса, как так

public class MyTemplate<T1, T2> {
    public T1 Prop1 { get; set; }
    public T2 Prop2 { get; set; }
}

public class MyTemplate<T1> : MyTemplate<T1, string>{}

C# не поддерживает такую функцию.

Как вы сказали, Вы можете подкласс его (если он не запечатан, и дублировать все объявления конструктора), но это совершенно другое дело.

к сожалению, C# не поддерживает то, что вы пытаетесь сделать. Это было бы трудно реализовать, учитывая, что тип по умолчанию для параметра должен был бы придерживаться общих ограничений и, скорее всего, создавал бы головные боли, когда среда CLR пыталась обеспечить безопасность типа.