Подтвердить что ты не робот

Перегрузка метода на основе общих ограничений?

Можно ли каким-то образом перегружать методы, которые отличаются только ограничениями общего типа?

Это не скомпилируется:

    void Foo<T>(T bar) where T : class
    {

    }

    void Foo<T>(T bar) where T : struct
    {

    }

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

Очевидным решением является не перегрузка, но мне интересно, почему это не работает на С#?

Дополнительный вопрос: если это просто ограничение компилятора С#, разрешает ли IL такая перегрузка?

4b9b3361

Ответ 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
}