8

私はすでに数日前からこの (メタ) 質問について考えています:
有効な C# インターフェイスを定義することは可能ですか?

この質問の考えられるバリエーション: Is it possible to define such interface in C# 2.0, 3.0, 4.0, 5.0 ? 実装時にコンパイルさえしない、またはコンパイルしても実行時例外をスローするようなインターフェースを定義することは可能ですか?

編集:そのようなインターフェースは定義上役に立たないことはわかっていますが、講義やプログラミングの仕事の応募者がC#をどれだけ知っているかをテストするための良い答えです。

4

4 に答える 4

17

実装できない有効な C# インターフェイスを定義することは可能ですか?

このトリビアの質問は、StackOverflow には適していませんが、簡単に答えられます。(間違っていることが判明しました!読んでください!)

class C
{
    private C() {}
}
interface IFoo<T> where T : C, new()
{
}

IFoo<T>Tの代わりに使用できる型引数がないため、を実装することはできませんTCは、パラメーターなしのパブリック コンストラクターを持たないため機能しません。また、既定のコンストラクターがプライベートであるため、C派生クラスが存在しない可能性があります。C(まあ、アクセス可能なCinsideの派生クラスがあるかもしれCませんが、この場合はありません。)


更新: コメンター「mike z」が正しく指摘している

class X<T> : IFoo<T> where T : C, new() {}

インターフェースを実装しますが、もちろんインスタンス化する方法はありませんX<T>!

さらに良いことに、ユーザー "GranBurguesa" は、プライベート コンストラクターを呼び出さない限り、C の派生クラスを宣言することが許可されていると指摘しています。これは、インスタンス化時にクラッシュして停止した場合にのみ可能です。(まあ、うるさいですが、再帰呼び出しがクラッシュの代わりに無限ループに最適化されることも許可されます。)

どちらの巧妙な回避策も、哲学的な問題を提起します。インターフェイスが誰もインスタンス化できないクラスによって実装されている場合、それは本当に実装されているのでしょうか? もちろん、GranBurguesa はそれIFoo<D>を実装して構築できることを示しているので、私の答えは実際には間違っています。


SLaks の削除された回答で示唆されているような、ジェネリック メカニズムの悪用が「無限」型につながるケースもあります。このような型は、CLR では有効ではありません。C# 設計チームは、C# コンパイラ仕様に同様の言語を追加することを検討しましたが、まだ実現していません。これらの型を使用すると、コンパイラまたはランタイムがクラッシュする可能性があります。

コンパイラをクラッシュさせる無限型の例については、私の記事を参照してください。

無限に、しかし超えない


これが1つです。このコードをカット アンド ペーストして Visual Studio に貼り付けると、このインターフェイスを実装できないことがわかります。

interface ΙAmAPerfectlyOrdinaryInterface { }

class C : IAmAPerfectlyOrdinaryInterface { }

于 2013-05-28T04:58:00.060 に答える
7

古いインターフェイスを除外しようとしている場合は、インターフェイスをObsoleteAttribute属性でマークできます。

編集: @Magnusがコメントに記載されているように、属性をその使用法に設定するErrortrue、エラーが発生します。

于 2013-05-27T19:39:03.963 に答える
5

型がアクセス可能で封印されていない場合、外部コードがその型のインスタンスを作成する可能性があり、基本型がそれに対してできることは実際には何もありません。「完全な信頼」やリフレクションは必要ありません。

public class CantDeriveMe
{
    private CantDeriveMe()
    {
    }
    public override string ToString()
    {
        return "My type is " + this.GetType().ToString();
    }
}

public class OhYeah : CantDeriveMe
{
    static OhYeah CapturedInstance;

    ~OhYeah()
    {
        CapturedInstance = this;
    }

    OhYeah() : this(1/String.Empty.Length)
    {
    }
    OhYeah(int blah) : this()
    {
    }
    public static OhYeah Create()
    {
        try
        {
            new OhYeah(4);
        }
        catch (DivideByZeroException)
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
        return CapturedInstance;
    }
    public static void test()
    {
        OhYeah it;
        it = OhYeah.Create();
        Console.WriteLine("Result was ({0})", it);
    }
}

コードが C# のみで記述されている場合、オブジェクトが正当な型ではないことに気付いた場合、基底クラスのデストラクタが鳴る可能性があることに注意してFinalizeください。親。

structタイプの組み合わせが満たすことができなかった と クラスの制約を組み合わせて、オープンなジェネリック インターフェイスを指定することは可能だと思います。

public interface evil<T, U>
    where T : struct,U
    where U : class

ただし、そのようなオープン ジェネリック型が本当に「インターフェイス」と見なされるのか、それともクローズド ジェネリック型だけが実際にインターフェイス (またはクラス、構造体) と見なされるのかはわかりません。

于 2013-06-01T00:28:36.687 に答える