「where T:class、new()」はどういう意味ですか?


回答:


329

これは、ジェネリックパラメーターに対する制約Tです。これはclass(参照型)である必要があり、パラメーターのないデフォルトのデフォルトコンストラクターが必要です。

手段は、そのTことができないintfloatdoubleDateTimeまたは他の任意のstruct(値型)。

それは可能性がstringある限り、それはデフォルトまたはパラメータなしのコンストラクタを持っているとして、またはその他のカスタム参照型。


5
あなたはここで、T ...、それはint型を使用しても安全である、フロート、ダブルなどの一部としてクラスの句を持っていない場合だけで、明確にする
AboutDev

1
@AboutDev正解です。ジェネリック型パラメーターに制約を課す必要はありません。ただし、参照型または値型でのみ機能することを期待するジェネリックを作成する場合は、指定する必要があります。制約がなければ、参照型(クラス)または値型(構造体(int、float、double ...))を期待できます。
NerdFury 2013

1
T:[インターフェイス名]、new()はどうですか?パラメータのないコンストラクタがまだ必要ですか?
Vince Tino、

3
Justinのコメントを明確にするために、空のコンストラクターにはステートメント(デフォルトのコンストラクターのような)がありませんが、パラメーターのないコンストラクターにはステートメント(リストの初期化のような)が含まれる場合があります。
DharmaTurtle 2016年

@VinceTino:new()「パブリックパラメータ
レス

162

これらは一般的な型制約です。あなたの場合にはそれらの2つがあります:

where T : class

タイプTは参照タイプ(値タイプではない)でなければならないことを意味します。

where T : new()

型にTはパラメーターのないコンストラクターが必要であることを意味します。この制約があるとT field = new T();、コード内では、他の方法では実行できないようなことを実行できます。

次に、コンマを使用して2つを組み合わせて取得します。

where T : class, new()

2番目と3番目の良い点は、情報を追加するためだけに、ジェネリック型でリフレクションを行うときに2番目の点が役立つと思います。例えば。T t = new T(); t.GetType()。GetProperty( "ID")。SetValue(t、uniqueId、null);
ジェリーリャン

1
構造体はデフォルトのコンストラクターを持つことができないため、new()はすでにクラスを暗黙指定しているので、T:class、new()の場所を言うのは冗長です。
DharmaTurtle 2016年

@DharmaTurtle、「構造体に明示的なパラメーターなしのコンストラクターを含めることはできません」は、それらにコンストラクターがないことを意味するのではなく、定義できないことを示しています。ソース:msdn.microsoft.com/tr-tr/library/aa288208
v

121

ここでT:構造体

type引数は値の型でなければなりません。Nullable以外の任意の値タイプを指定できます。詳細については、「null許容型の使用(C#プログラミングガイド)」を参照してください。

ここでT:クラス

type引数は、クラス、インターフェイス、デリゲート、または配列型を含む参照型でなければなりません。(下記の注を参照してください。)

ここでT:new() 型引数には、パラメーターなしのパブリックコンストラクターが必要です。他の制約と組み合わせて使用​​する場合、new()制約を最後に指定する必要があります。

ここでT:[基本クラス名]

type引数は、指定された基本クラスであるか、それから派生している必要があります。

ここでT:[インターフェース名]

type引数は、指定されたインターフェイスであるか、実装されている必要があります。複数のインターフェース制約を指定できます。制約インターフェースは、汎用的なものにすることもできます。

ここでT:U

Tに提供される型引数は、Uに提供される引数であるか、それから派生する必要があります。これは、ネイキッド型制約と呼ばれます。


23
これは役に立ちましたが、sourceにリンクしています
Skean

26

classnew、ジェネリック型パラメーターのT 2つの制約です。
それぞれ彼らは保証します:

class

type引数は参照型でなければなりません。これは、クラス、インターフェイス、デリゲート、または配列型にも適用されます。

new

type引数には、パラメーターなしのパブリックコンストラクターが必要です。他の制約と一緒に使用する場合、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
}

1
良いデモンストレーション。ありがとう。
Subhan Ali

15

new(): new()制約を指定すると、タイプTはパラメーターなしのコンストラクターを使用する必要があるため、オブジェクトをインスタンス化できます。デフォルトのコンストラクターを参照してください。

クラス: 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();
    }
}

6

つまり、型Tはクラスあり、引数をとらないコンストラクターを持つ必要があります。

たとえば、これを実行できる必要があります。

T t = new T();

1
コンストラクタだけでなく、引数を取らないコンストラクタ。
NerdFury、2011年

@NerdFury:ありがとう。それは重要なビットです。訂正。
Evan Mulawski、2011年

5

where(C#リファレンス)

new()制約により、コンパイラーは、提供されるすべての型引数にアクセス可能なパラメーターなし(またはデフォルト)のコンストラクターが必要であることを認識させます

したがって、それはTクラスでなければならず、パラメータなしでアクセスできる、またはデフォルトのコンストラクタを持つ必要があります。


4

「Where」の後に続くのは、宣言したジェネリック型Tに対する制約なので、次のようになります。

  • classは、Tがクラスであり、値の型や構造体ではないことを意味します。

  • new()は、Tクラスにパブリックパラメータのないデフォルトコンストラクタを定義する必要があることを示します。


1

これは、ジェネリックパラメーターTの「制約」と呼ばれます。つまり、Tは参照型(クラス)である必要があり、デフォルトのパブリックコンストラクターが必要です。


1

これはGenericsメカニズムの一部であり、whereキーワードは、型パラメーターとして使用するために実装する必要がある型に制約を追加します。


0

制約でクラスを使用する場合は、参照タイプのみを使用できることを意味します。追加するもう1つのことは、制約new()を使用する場合です。これは、制約条件で最後に記述する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.