public T GetMyClass <T>() где T: MyClass, new () {/ * это бессмысленно? * /} - PullRequest
4 голосов
/ 14 июля 2011

два метода в классе "Confused" ниже одинаковы?

class MyClass
{
    public override string ToString()
    {
        return "I am confused now";
    }
}

class Confused
{    
    public MyClass GetMyClass()
    {
        return new MyClass();
    }

    public T GetMyClass<T>() where T : MyClass, new()
    {
        return System.Activator.CreateInstance<T>();
    }
}

class Program
{
    static void Main()
    {
        Confused c = new Confused();
        System.Console.WriteLine(c.GetMyClass());
        System.Console.WriteLine(c.GetMyClass<MyClass>());
    }
}

Они производят разные IL, но есть ли причина писать универсальную версию, отличную от «прямой» версии, кроме того, чтобы сбить с толку коллег:)

Ответы [ 8 ]

4 голосов
/ 14 июля 2011

Если вы напишите универсальную версию, вы можете создать и вернуть производные классы:

where T : MyClass

Кроме того, в общей версии вам не нужен код активации:

return new T();

Это потому что вы указали:

where T : new()

Общее ограничение, применяющее открытый конструктор без параметров.

2 голосов
/ 14 июля 2011

Конечно, есть разница.Допустим, у вас есть второй класс, производный от MyClass:

class MyClass2 : MyClass { }

Тогда вы можете сделать

MyClass2 myClass2 = confused.GetMyClass<MyClass2>();

Вы не можете сделать это с другой функцией.

1 голос
/ 14 июля 2011

Существует очень большая разница:
Неуниверсальная версия может возвращать только экземпляры типа MyClass, тогда как универсальная версия может возвращать экземпляры типа MyClass и все классы, производные от MyClass!

1 голос
/ 14 июля 2011

MyClass может быть базовым классом (или интерфейсом IMyClass).Универсальная версия с ограничением говорит, что вы хотите, чтобы эта функция работала для любого класса, производного (или реализующего) общую базу или интерфейс, и возвращала результат как этот производный класс, а не как базу.

class MyClass { }
class MySpecializedClass : MyClass { } 
// etc.
0 голосов
/ 14 июля 2011

Они не одинаковы.Универсальный позволяет также наследовать унаследованные классы следующим образом:

class MyClass
{
    public override string ToString()
    {
        return "I am confused now";
    }
}

class InheritedClass : MyClass
{
}

class Confused
{
    public MyClass GetMyClass()
    {
        return new MyClass();
    }

    public T GetMyClass<T>() where T : MyClass, new()
    {
        return System.Activator.CreateInstance<T>();
    }
}

class Program
{
    static void Main()
    {
        Confused c = new Confused();
        System.Console.WriteLine(c.GetMyClass());
        System.Console.WriteLine(c.GetMyClass<MyClass>());
        System.Console.WriteLine(c.GetMyClass<InheritedClass>());
    }
}
0 голосов
/ 14 июля 2011

Они дали бы тот же результат ТОЛЬКО если бы вы позвонили .GetMyClass<MyClass>(). Тем не менее, я предполагаю, что дополнительный метод был создан для создания других классов? Если нет, то они одинаковые, так что излишний (и я бы избавился от универсальной версии, которая содержит служебные данные внутри сборки).

Они используются по-другому?

0 голосов
/ 14 июля 2011

Я не совсем уверен, но Generics - это функция времени выполнения в .NET. Следовательно, неуниверсальный метод не эквивалентен универсальному, даже если он используется эквивалентно. Поскольку они общедоступны, их нельзя оптимизировать.

0 голосов
/ 14 июля 2011

Нет.Они не то же самое.Первый будет когда-либо только создавать объект MyClass, а второй будет создавать любой объект, который является MyClass или потомком MyClass, на основе параметра типа.

...