web-dev-qa-db-ja.com

C#のインターフェイス内で使用される場合、「new」キーワードはどういう意味ですか?

インターフェイスジェネリックの開発インターフェイスでコンストラクターを宣言したかったのですが、コンストラクターはそこで禁止されていると書かれています。静的ファクトリメソッドを宣言しようとしましたが、どちらの静的メソッドも許可されていないと表示され、「new」キーワードの使用を提案しています。しかし、C#のインターフェイス内で使用した場合、「new」キーワードが正確に何を意味するのか、私にはほとんどわかりません。ありますか?

更新:

2つの質問を混ぜたくなかったので、サンプルコードを投稿しませんでした。インターフェイスでコンストラクタ/ファクトリを指定する方法と、インターフェイスでの「new」キーワードの意味です。 StackOverflowが2番目の質問を純粋な形式で受け入れず、品質基準を満たしていないため、最初の部分を指定することを余儀なくされました。

しかし、あなたが要求するように、私は私が達成しようとしていたことをサンプリングします:

Interface IMyInterface <T, U, V>
{
    IMyInterface (T, U, U);
    // OR
    static IMyInterface GetNewIMyInterface (T, U, U);
}

すべての派生クラスにそのようなコンストラクターを実装してほしいだけです。

25
Ivan

newキーワードは、インターフェースが拡張している可能性のあるインターフェースに含まれる定義を定義が非表示にすることをコンパイラーに通知します。

29
Bala R

Balaの答えは正しいですが、これを実行したいwhyを確認すると役立つ場合があります。 CLRバージョン2のライブラリを設計するときに、BCL設計者が直面した問題について考えてみます。既存のインターフェイスがありました。

interface IEnumerable
{
  IEnumerator GetEnumerator();
}

今、あなたは追加したい:

interface IEnumerable<T> : IEnumerable
{
  new IEnumerator<T> GetEnumerator();
}

新しいインターフェイスは、戻り値の型のみが古いインターフェイスと異なります。

あなたの選択は何ですか?

1)新しいGetEnumeratorを「新規」としてマークして、これが同じ名前で戻り値の型が異なる古いメソッドと競合しない新しいメソッドであることをコンパイラーが認識できるようにします。

2)名前をGetEnumerator2に変更します。

3)元のIEnumerableから継承しないでください。

オプション2と3はひどいです。オプション1は素晴らしいです。新しい列挙型は古い列挙型を期待するコードとシームレスに連携しますが、新しい列挙型を使用するように記述されたコードは、デフォルトで「新しい」ジェネリック動作を取得します。

66
Eric Lippert

インターフェイスでコンストラクターまたは静的メソッドを指定することはできません...canは、ジェネリック型パラメーターの型制約を追加します。

void Foo<T>() where T : new()
{
    T t = new T();
    // Do stuff with t
}

それはあなたが考えていることですか?

4
Jon Skeet

インターフェイスはコントラクトを指定することになっています。メソッドシグネチャのみが含まれ、実装は含まれません。インターフェイスを直接インスタンス化することはできないため、インターフェイスでコンストラクタを使用することはできません。

http://msdn.Microsoft.com/en-us/library/87d83y5b(v = vs.80).aspx

3

インターフェイスを使用していますが、代わりに基本クラスが必要なようです。インターフェイスには、コンストラクターで初期化する必要のあるフィールドを含めることができないため、コンストラクターは必要ありません。代わりに基本クラスを使用したいと思います。

3
Coeffect

まず、「new」キーワードが実際に行うのは、「new」キーワードを使用する必要があるという警告を生成しないようにコンパイラーに指示することだけです。警告を取り除くことを除けば、キーワード自体は(問題のコンテキストでは)何もしません。

現在、コンパイラは、継承元のインターフェイスですでに定義されているメンバー(プロパティまたはメソッド)を再定義するときに「new」キーワードを使用することを望んでいます。これを行う理由は少なくとも2つ考えられます。まず、前述のEric Lippertのように、メソッドが別の型を返す(または同じ名前のプロパティを別の型で定義する)ことが必要な場合があります。もう1つの可能性は、2つのインターフェースに異なる実装を定義する場合です。

_interface A
{
    void a();
}

interface B : A
{
    new void a();
}

class C : B
{
    void A.a() { Console.WriteLine("Called by interface A!"); }
    void B.a() { Console.WriteLine("Called by interface B!"); }
}

static class Test
{
    public static void DoTest()
    {
        B b = new C();
        b.a();       // Produces "Called by interface B!"
        ((A)b).a();  // Produces "Called by interface A!"
    }
}
_

BでB.a()を再定義せずにCでa()を定義しようとすると、インターフェイスのメンバーではないという警告が表示されます。明示的なインターフェイス宣言では、次のインターフェイスを使用する必要があります。メンバーは明示的に定義されています。

2
M Kloster

C#および.NETでは、インターフェイスでコンストラクターを宣言することはできません。

それは単にそのインターフェースを実装するという明示された制約でなければなりません(.NETライブラリの ISerializable を参照)。

考えてみれば、コンストラクターを呼び出すときに作成する具象クラスを知っている必要があるため、インターフェイスにコンストラクターを設定しても意味がありません。このようなインターフェイスコンストラクターをどのように呼び出すと、結果はどうなりますか?

0
thecoop