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

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

Можно ли это сделать или приблизиться к С#?

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

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

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

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

Было бы существенно:

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

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

Ответ 1

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

Я бы подклассифицировал ваш основной родовой класс:

class BaseGeneric<T,U>

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

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

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

Ответ 2

Одним из решений является подклассов. Другой, который я использовал бы, - это методы factory (в сочетании с ключевым словом 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>.

Ответ 3

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

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

Ответ 4

вы также можете создать класс Overload как таковой

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

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

Ответ 5

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