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

Не могли бы вы объяснить мне, что означает where T : class, new() в следующей строке кода?

void Add<T>(T item) where T : class, new();

person Rawhi    schedule 19.01.2011    source источник
comment
для дальнейшего использования: msdn.microsoft.com/en-us/library/d5x73970. aspx   -  person Ahmet Kakıcı    schedule 11.10.2013


Ответы (11)


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

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

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

person NerdFury    schedule 19.01.2011
comment
Чтобы уточнить, если у вас нет предложения class как части where T ..., тогда безопасно использовать int, float, double и т. Д. - person AboutDev; 09.02.2013
comment
@AboutDev правильно, вам не нужно накладывать ограничения на параметр универсального типа. Но если вы создаете универсальный шаблон, который рассчитывает работать только со ссылочными типами или типами значений, вам следует указать. Без ограничения вы можете ожидать ссылочные типы (классы) или типы значений (структуры (int, float, double ...)). - person NerdFury; 12.02.2013
comment
А как насчет того, где T: [имя интерфейса], new ()? Вам все еще нужен конструктор без параметров? - person Vince Tino; 12.10.2015
comment
Чтобы прояснить комментарий Джастина, пустой конструктор не имеет операторов (например, конструктор по умолчанию), в то время как конструктор без параметров может содержать операторы (например, инициализация списка). - person DharmaTurtle; 03.01.2016
comment
@VinceTino: new() точно указывает, что должен иметь общедоступный конструктор без параметров - person Flater; 09.11.2019
comment
К моему величайшему удивлению new() также исключает конструкторы с одним параметром и значением по умолчанию для него ... По крайней мере, я считаю это неинтуитивным. - person mBardos; 29.01.2021

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

where T : class

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

where T : new()

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

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

where T : class, new()
person Justin Niessner    schedule 19.01.2011
comment
Хорошие моменты для второго и третьего, просто чтобы добавить информацию, я думаю, что второй пункт полезен при отражении в общем типе. например. T t = новый T (); t.GetType (). GetProperty (ID) .SetValue (t, uniqueId, null); - person Jerry Liang; 13.03.2013
comment
Я считаю излишним говорить, где T: class, new (), поскольку new () уже подразумевает класс, потому что у структур не может быть конструкторов по умолчанию. - person DharmaTurtle; 03.01.2016
comment
@DharmaTurtle, структуры не могут содержать явных конструкторов без параметров, не означает, что у них их нет, это говорит о том, что вы не можете их определить. источник: msdn.microsoft.com/tr-tr /library/aa288208(v=vs.71).aspx - person rustem; 06.12.2016

где T: struct

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

где T: класс

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

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

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

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

где T: [название интерфейса]

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

где T: U

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

person Mohammed Jubayer    schedule 20.05.2013
comment
Это было полезно, но ссылка на источник. - person Skean; 08.01.2015

class & new - это 2 ограничений для параметр универсального типа T.
Соответственно, они обеспечивают:

class

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

new

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

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

Пример:

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
}
person Sergio    schedule 26.06.2017
comment
Хорошая демонстрация. Спасибо. - person Subhan Ali; 05.09.2018

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();
    }
}
person Brendan    schedule 20.10.2013

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

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

T t = new T();
person Evan Mulawski    schedule 19.01.2011
comment
не просто конструктор, а конструктор, который не принимает аргументов. - person NerdFury; 19.01.2011
comment
@NerdFury: Спасибо. Это важный момент. Исправленный. - person Evan Mulawski; 19.01.2011

where (Справочник по C #)

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

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

person Fredrik Widerberg    schedule 19.01.2011

То, что идет после "Где", является ограничением для объявленного вами универсального типа T, поэтому:

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

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

person Otman IGHOULASSEN    schedule 11.03.2017

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

person Community    schedule 19.01.2011

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

person Peter Lillevold    schedule 19.01.2011

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

person Rebwar    schedule 02.04.2020