Зачем использовать универсальный метод с ограничением типа вместо самого типа?

14

В другом вопросе StackExchange я заметил, что кто-то использует этот прототип:

void DoSomething<T>(T arg) where T: SomeSpecificReferenceType
{
    //Code....
}

Принимая во внимание, что есть только один тип ограничений ( SomeSpecificReferenceType), в чем разница и преимущество такого написания, а не просто:

void DoSomething(SomeSpecificReferenceType arg)
{
    //Code....
}

В обоих случаях argбудет проводиться проверка типов во время компиляции. В обоих случаях тело метода может безопасно полагаться на знания, argотносящиеся (или являющиеся потомками) к конкретному типу, известному во время компиляции.

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

Джон Ву
источник
Я едва знаю C #, так что это только предположение, но разве это не позволяет более эффективную статическую диспетчеризацию вместо динамической диспетчеризации?
Антон Барковский

Ответы:

13

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

Да, это возможно.

Или есть законная причина, почему подпись метода будет написана таким образом?

Может быть . Как правило, было бы более разумно, если бы использовалось возвращаемое значение Tили другой используемый параметр T.

Но возможно, что внутреннее содержимое кода использует T(возможно, в качестве аргумента для сериализатора?) И должно использовать конкретно, Tа не класс ограничений. Иногда вы увидите, что когда ограничение является интерфейсом, сопряженным с newограничением, и внутренности метода Tпо какой-то причине создают s.

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

Telastyn
источник
1

Я думаю, что я помню себя, набирая ответ, содержащий это.

В то время причина была такой:
(Код может быть другим. Просто для иллюстрации одной из возможных причин, по которой существует ограничение на параметр типа в универсальном методе.)

class SomeSingleton
{
    static Dictionary<Type, List<object>> staticTypeSpecificList;
    public void AddObjectToList<T>(T t) where T : SomeCommonThing
    {
        Type tt = t.GetType();
        List<object> list;
        if (!staticTypeSpecificList.TryGet(tt, out list))
        {
            list = new List<object>();
            staticTypeSpecificList.Add(tt, list);
        }
        list.Add(t);
    }
}

По сути, код сам выполняет ручное кодирование манипуляций с типами. Это может также быть смешано с некоторыми вещами отражения.

Например, используя Method<T>(T arg) where T : ..., можно заменить arg.GetType()на typeof(T). Хотя я не знаю, хорош этот выбор или плох.

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

rwong
источник
msgstr "можно заменить arg.GetType () на typeof (T)". Это полезно, когда arg может действительно быть нулевым, например, в некоторых случаях сериализации.
Walpen