O que significa “where T: class, new ()”?

Respostas:

329

Essa é uma restrição no parâmetro genérico T. Ele deve ser um class(tipo de referência) e deve ter um construtor padrão sem parâmetro público.

Isso significa que Tnão pode ser um int, float, double, DateTimeou qualquer outro struct(tipo de valor).

Pode ser um stringou qualquer outro tipo de referência personalizado, desde que tenha um construtor padrão ou sem parâmetros.

NerdFury
fonte
5
Só para esclarecer, se você não tem a cláusula de classe como parte do onde T ..., então é seguro para uso int, float, double, etc
AboutDev
1
@AboutDev correto, você não precisa colocar restrições no seu parâmetro de tipo genérico. Mas se você estiver criando um genérico que espera funcionar apenas em tipos de referência ou valor, deverá especificar. Sem uma restrição, você pode esperar tipos de referência (classes) ou tipos de valor (estruturas (int, float, double ...)).
NerdFury
1
E onde T: [nome da interface], novo ()? Você ainda precisa ter um construtor sem parâmetros?
Vince Tino
3
Para esclarecer o comentário de Justin, um construtor vazio não possui instruções (como o construtor padrão), enquanto um construtor sem parâmetros pode conter instruções (como inicializar uma lista).
DharmaTurtle
@VinceTino: new()precisamente especifica "deve ter um construtor sem parâmetros público"
Flater
162

Essas são restrições de tipo genérico. No seu caso, existem dois deles:

where T : class

Significa que o tipo Tdeve ser um tipo de referência (não um tipo de valor).

where T : new()

Significa que o tipo Tdeve ter um construtor sem parâmetros. Ter essa restrição permitirá que você faça algo como T field = new T();no seu código que você não seria capaz de fazer de outra maneira.

Você então combina os dois usando uma vírgula para obter:

where T : class, new()
Justin Niessner
fonte
Bons pontos para o segundo e terceiro, apenas para adicionar informações, acho que o segundo ponto é útil quando se faz reflexão em tipo genérico. por exemplo. Tt = novo T (); t.GetType (). GetProperty ("ID"). SetValue (t, uniqueId, null);
Jerry Liang
1
Eu acredito que é redundante dizer onde T: class, new (), já que new () já implica classe porque structs não podem ter construtores padrão.
DharmaTurtle
@DharmaTurtle, "structs não podem conter construtores explícitos sem parâmetros", não significa que eles não tenham um, diz que você não pode definir um. fonte: msdn.microsoft.com/tr-tr/library/aa288208(v=vs.71).aspx
Rustem
121

onde T: struct

O argumento type deve ser um tipo de valor. Qualquer tipo de valor, exceto Nullable, pode ser especificado. Consulte Usando tipos nulos (Guia de programação em C #) para obter mais informações.

onde T: classe

O argumento type deve ser um tipo de referência, incluindo qualquer classe, interface, delegado ou tipo de matriz. (Ver nota abaixo.)

onde T: new () O argumento type deve ter um construtor público sem parâmetros. Quando usada em conjunto com outras restrições, a nova restrição () deve ser especificada por último.

onde T: [nome da classe base]

O argumento type deve ser ou derivar da classe base especificada.

onde T: [nome da interface]

O argumento type deve ser ou implementar a interface especificada. Múltiplas restrições de interface podem ser especificadas. A interface de restrição também pode ser genérica.

onde T: U

O argumento de tipo fornecido para T deve ser ou derivar do argumento fornecido para U. Isso é chamado de restrição de tipo simples.

Mohammed Jubayer
fonte
23
Isso foi útil, mas link para a fonte .
Skean
26

class& newsão 2 restrições no parâmetro de tipo genéricoT .
Respectivamente, eles garantem:

class

O argumento type deve ser um tipo de referência; isso se aplica também a qualquer classe, interface, delegado ou tipo de matriz.

new

O argumento type deve ter um construtor público sem parâmetros. Quando usada junto com outras restrições, a nova restrição () deve ser especificada por último.

Sua combinação significa que o tipo Tdeve ser um Tipo de Referência (não pode ser um Tipo de Valor ) e deve ter um construtor sem parâmetros.

Exemplo:

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
fonte
1
Boa demonstração. Obrigado.
Subhan Ali
15

new (): especificar a restrição new () significa que o tipo T deve usar um construtor sem parâmetros, para que um objeto possa ser instanciado a partir dele - consulte Construtores padrão .

classe: significa que T deve ser um tipo de referência para que não possa ser um int, float, double, DateTime ou outra estrutura (tipo de valor).

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
fonte
6

Isso significa que esse tipo Tdeve ser uma classe e ter um construtor que não aceita argumentos.

Por exemplo, você deve conseguir fazer isso:

T t = new T();
Evan Mulawski
fonte
1
não apenas um construtor, mas um construtor que não aceita argumentos.
NerdFury 19/01
@NerdFury: Obrigado. Isso é um pouco importante. Corrigido.
Evan Mulawski
5

where (Referência de C #)

A nova restrição () permite que o compilador saiba que qualquer argumento de tipo fornecido deve ter um construtor acessível sem parâmetros - ou padrão -

Portanto, deve ser, Tdeve ser uma classe e ter um construtor acessível sem parâmetros - ou padrão.

Fredrik Widerberg
fonte
4

O que vem depois do "Onde" é uma restrição no tipo genérico T que você declarou, portanto:

  • classe significa que o T deve ser uma classe e não um tipo de valor ou uma estrutura.

  • new () indica que a classe T deve ter um construtor padrão público sem parâmetros definido.

Otman IGHOULASSEN
fonte
1

É chamado de 'restrição' no parâmetro genérico T. Isso significa que T deve ser um tipo de referência (uma classe) e que deve ter um construtor público padrão.


fonte
1

Isso faz parte do mecanismo Genéricos, onde a palavra-chave where adiciona restrições a quais tipos devem ser implementados para serem usados ​​como parâmetros de tipo.

Peter Lillevold
fonte
0

ao usar a classe em restrições, significa que você só pode usar o tipo de referência; outra coisa a acrescentar é quando usar a restrição new () ; deve ser a última coisa que você escreve nos termos das restrições.

Rebwar
fonte