Что означает «где T: class, new ()»?

Ответы:

329

Это ограничение общего параметра T. Он должен быть class(ссылочный тип) и должен иметь открытый конструктор по умолчанию без параметров.

Это означает Tне может быть int, float, double, DateTimeили любой другой struct(тип значения).

Это может быть stringили любой другой пользовательский ссылочный тип, если он имеет конструктор по умолчанию или без параметров.

NerdFury
источник
5
Просто чтобы уточнить, если у вас нет предложения class как части, где T ..., тогда безопасно использовать int, float, double и т. Д.
AboutDev
1
@AboutDev правильно, вам не нужно накладывать ограничения на ваш параметр универсального типа. Но если вы создаете универсальный шаблон, который рассчитан на работу только с ссылочными типами или типами значений, вам следует указать. Без ограничения вы можете ожидать ссылочные типы (классы) или типы значений (структуры (int, float, double ...)).
NerdFury
1
Как насчет где T: [имя интерфейса], new ()? Вам все еще нужен конструктор без параметров?
Винс Тино
3
Чтобы пояснить комментарий Джастина, пустой конструктор не имеет операторов (например, конструктор по умолчанию), в то время как конструктор без параметров может содержать операторы (например, инициализация списка).
DharmaTurtle
@VinceTino: new()точно указывает «должен иметь открытый конструктор без параметров»
Flater
162

Это ограничения общего типа. В вашем случае их два:

where T : class

Означает, что тип Tдолжен быть ссылочным типом (а не типом значения).

where T : new()

Означает, что тип Tдолжен иметь конструктор без параметров. Наличие этого ограничения позволит вам сделать что-то подобное T field = new T();в вашем коде, что вы не сможете сделать иначе.

Затем вы объединяете их, используя запятую, чтобы получить:

where T : class, new()
Джастин Нисснер
источник
Хорошие моменты для второго и третьего, просто чтобы добавить информацию, я думаю, что второй пункт полезен при отражении в обобщенном типе. например. T t = новый T (); t.GetType (). GetProperty ("ID"). SetValue (t, uniqueId, null);
Джерри Лян
1
Я считаю излишним говорить, где T: class, new (), поскольку new () уже подразумевает класс, потому что структуры не могут иметь конструкторы по умолчанию.
DharmaTurtle
@DharmaTurtle, «структуры не могут содержать явных конструкторов без параметров», не означает, что у них их нет, это говорит о том, что вы не можете их определить. источник: msdn.microsoft.com/tr-tr/library/aa288208(v=vs.71).aspx
rustem
121

где T: структура

Аргумент типа должен быть типом значения. Можно указать любой тип значения, кроме Nullable. Посмотрите Использование Обнуляемых Типов (Руководство по программированию C #) для получения дополнительной информации.

где Т: класс

Аргумент типа должен быть ссылочным типом, включая любой класс, интерфейс, делегат или тип массива. (См. Примечание ниже.)

где T: new () Аргумент типа должен иметь открытый конструктор без параметров. При использовании в сочетании с другими ограничениями ограничение new () должно указываться последним.

где T: [имя базового класса]

Аргумент типа должен быть или наследоваться от указанного базового класса.

где T: [имя интерфейса]

Аргумент типа должен быть или реализовывать указанный интерфейс. Можно указать несколько ограничений интерфейса. Ограничивающий интерфейс также может быть универсальным.

где Т: У

Аргумент типа, предоставленный для T, должен быть или получен из аргумента, предоставленного для U. Это называется ограничением типа «голый».

Мохаммед Джубайер
источник
23
Это было полезно, но ссылка на источник .
Скин
26

class& new2 ограничения на параметр общего типаT .
Соответственно они обеспечивают:

class

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

new

Аргумент типа должен иметь открытый конструктор без параметров. При использовании вместе с другими ограничениями ограничение new () должно указываться последним.

Их комбинация означает, что тип Tдолжен быть ссылочным типом (не может быть типом значения ) и должен иметь конструктор без параметров.

Пример:

struct MyStruct { } // structs are value types

class MyClass1 { } // no constructors defined, so the class implicitly has a parameterless one

class MyClass2 // parameterless constructor explicitly defined
{
    public MyClass2() { }
}

class MyClass3 // only non-parameterless constructor defined
{
    public MyClass3(object parameter) { }
}

class MyClass4 // both parameterless & non-parameterless constructors defined
{
    public MyClass4() { }
    public MyClass4(object parameter) { }
}

interface INewable<T>
    where T : new()
{
}

interface INewableReference<T>
    where T : class, new()
{
}

class Checks
{
    INewable<int> cn1; // ALLOWED: has parameterless ctor
    INewable<string> n2; // NOT ALLOWED: no parameterless ctor
    INewable<MyStruct> n3; // ALLOWED: has parameterless ctor
    INewable<MyClass1> n4; // ALLOWED: has parameterless ctor
    INewable<MyClass2> n5; // ALLOWED: has parameterless ctor
    INewable<MyClass3> n6; // NOT ALLOWED: no parameterless ctor
    INewable<MyClass4> n7; // ALLOWED: has parameterless ctor

    INewableReference<int> nr1; // NOT ALLOWED: not a reference type
    INewableReference<string> nr2; // NOT ALLOWED: no parameterless ctor
    INewableReference<MyStruct> nr3; // NOT ALLOWED: not a reference type
    INewableReference<MyClass1> nr4; // ALLOWED: has parameterless ctor
    INewableReference<MyClass2> nr5; // ALLOWED: has parameterless ctor
    INewableReference<MyClass3> nr6; // NOT ALLOWED: no parameterless ctor
    INewableReference<MyClass4> nr7; // ALLOWED: has parameterless ctor
}
Sergio
источник
1
Хорошая демонстрация. Спасибо.
Субхан Али
15

new (): Указание ограничения new () означает, что тип T должен использовать конструктор без параметров, поэтому объект может быть создан из него - см. Конструкторы по умолчанию .

class: означает, что T должен быть ссылочным типом, поэтому он не может быть int, float, double, DateTime или другой структурой (тип значения).

public void MakeCars()
{
    //This won't compile as researchEngine doesn't have a public constructor and so can't be instantiated.
    CarFactory<ResearchEngine> researchLine = new CarFactory<ResearchEngine>();
    var researchEngine = researchLine.MakeEngine();

    //Can instantiate new object of class with default public constructor
    CarFactory<ProductionEngine> productionLine = new CarFactory<ProductionEngine>();
    var productionEngine = productionLine.MakeEngine();
}

public class ProductionEngine { }
public class ResearchEngine
{
    private ResearchEngine() { }
}

public class CarFactory<TEngine> where TEngine : class, new()
{
    public TEngine MakeEngine()
    {
        return new TEngine();
    }
}
Brendan
источник
6

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

Например, вы должны быть в состоянии сделать это:

T t = new T();
Эван Мулавски
источник
1
не просто конструктор, но конструктор, который не принимает аргументов.
NerdFury
@NerdFury: Спасибо. Это важный момент. Исправлено.
Эван Мулавски
5

где (C # ссылка)

Ограничение new () позволяет компилятору знать, что любой предоставленный аргумент типа должен иметь доступный конструктор без параметров или по умолчанию

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

Фредрик Видерберг
источник
4

После «Где» находится ограничение на общий тип T, который вы объявили, поэтому:

  • класс означает, что T должен быть классом, а не типом значения или структурой.

  • new () указывает, что класс T должен иметь открытый конструктор по умолчанию без параметров.

Отман ИГУЛАССЕН
источник
1

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


источник
1

Это часть механизма Generics, в котором ключевое слово where добавляет ограничения к тем типам, которые должны быть реализованы для использования в качестве параметров типа.

Питер Лиллевольд
источник
0

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

Rebwar
источник