13

このインターフェースを定義した後:

public interface IInputBoxService<out T> {
    bool ShowDialog();
    T Result { get; }
}

次のコードが機能する理由:

public class StringInputBoxService : IInputBoxService<string> {
    ...
}

...

IInputBoxService<object> service = new StringInputBoxService();

そしてこれはしませんか?:

public class IntegerInputBoxService : IInputBoxService<int> {
    ...
}

...

IInputBoxService<object> service = new IntegerInputBoxService();

int が値型であることと何か関係がありますか? はいの場合、どうすればこの状況を回避できますか?

ありがとう

4

1 に答える 1

14

はい、それは絶対にint値型であることと関係があります。C# 4 の一般的な分散は、参照型でのみ機能します。これは主に、参照が常に同じ表現を持っているためです。参照は単なる参照であるため、CLR はオブジェクト参照と同様に文字列参照であることがわかっているものに対して同じビットを使用できます。IInputBoxService<object>CLR は、コードが安全であることを確認し、渡されたときだけを知っているネイティブ コードを使用することができます。IInputBoxService<string>返される値はResult表現的に互換性があります (そのような用語が存在する場合)。

int=>を使用objectすると、ボクシングなどが必要になるため、同じコードになってしまうことはありません。これは、基本的に分散を台無しにします。

編集: C# 4.0 仕様では、セクション 13.1.3.2 で次のように述べられています。

バリアンス アノテーションの目的は、インターフェイスおよびデリゲート型へのより寛大な (ただし、タイプ セーフな) 変換を提供することです。この目的のために、暗黙的 (§6.1) および明示的変換 (§6.2) の定義は、次のように定義される分散変換可能性の概念を利用します。インターフェイスまたはバリアント型パラメーター T で宣言されたデリゲート型、およびバリアント型パラメーター Xi ごとに、次のいずれかが保持されます。

  • Xi は共変であり、Ai から Bi への暗黙的な参照または恒等変換が存在します。

  • Xi は反変であり、Bi から Ai への暗黙的な参照または恒等変換が存在します。

  • Xi は不変であり、Ai から Bi への恒等変換が存在します。

これはそれほど明白ではありませんが、基本的に参照変換は参照型間でのみ存在し、同一性変換 (つまり、型からそれ自体へ) のみが残ります。

回避策については、基本的に独自のラッパー クラスを作成する必要があると思います。これは次のように簡単です。

public class Wrapper<T>
{
    public T Value { get; private set; }
    public Wrapper(T value)
    {
        Value = value;
    }
}

それはかなり厄介ですが:(

于 2010-04-28T06:37:11.393 に答える