Перегрузка метода на основе общих ограничений?
Можно ли каким-то образом перегружать методы, которые отличаются только ограничениями общего типа?
Это не скомпилируется:
void Foo<T>(T bar) where T : class
{
}
void Foo<T>(T bar) where T : struct
{
}
Так как это "открытые" методы, фактический метод должен быть закрыт/построен/полностью определен, когда он ссылается в другом месте кода с конкретным типом T
, и тогда будет ясно, какую перегрузку нужно вызвать.
Очевидным решением является не перегрузка, но мне интересно, почему это не работает на С#?
Дополнительный вопрос: если это просто ограничение компилятора С#, разрешает ли IL такая перегрузка?
Ответы
Ответ 1
Могу ли я каким-то образом перегружать методы, которые отличаются только ограничениями общего типа?
Нет. Это не часть сигнатуры метода с точки зрения перегрузки, как и тип возврата.
В некоторых случаях существуют ужасные способы "псевдоперегрузки", но я бы не рекомендовал идти по этому пути.
Для получения дополнительной информации вы можете прочитать:
Ответ 2
Это невозможно.
Общие ограничения не считаются частью сигнатуры метода для целей перегрузки.
Если вы хотите разрешить как типы значений, так и ссылочные типы, зачем вообще ограничивать?
Ответ 3
Обновление. В С# 7.3 общие ограничения теперь являются частью решения о перегрузке.
Итак, этот код скомпилируется:
class Animal { }
class Mammal : Animal { }
class Giraffe : Mammal { }
class Reptile : Animal { }
static void Foo<T>(T t) where T : Reptile { }
static void Foo(Animal animal) { }
static void Main()
{
Foo(new Giraffe());
}
Ответ 4
struct _Val_Trait<T> where T:struct { }
struct _Ref_Trait<T> where T:class { }
static void Foo<T>(T bar, _Ref_Trait<T> _ = default(_Ref_Trait<T>)) where T:class
{
Console.WriteLine("ref");
}
static void Foo<T>(T bar, _Val_Trait<T> _ = default(_Val_Trait<T>)) where T:struct
{
Console.WriteLine("val");
}
static void Main()
{
Foo(1); // -->"val"
Foo(DateTime.Now); // -->"val"
Foo(""); // -->"ref"
//but:
//Foo(null); - error: type cannot be inferred
}