7

ユースケースは次のようなものです:

public class SomeClass : ICloneable
{
    // Some Code

    // Implementing interface method
    public object Clone()
    {
        // Some Clonning Code
    }
}

ここで私の質問は、Funda の Covariance と Contravariance を考慮すると、Clone() メソッドの戻り値の型として "SomeClass(As it is distributed from object)" を使用できないのはなぜですか?

このマイクロソフトの実装の背後にある理由を誰か説明してもらえますか????

4

6 に答える 6

6

インターフェイス実装分散の壊れていない実装は、戻り値の型で共変であり、引数の型で反変でなければなりません。

例えば:

public interface IFoo
{
    object Flurp(Array array);
}

public class GoodFoo : IFoo
{
    public int Flurp(Array array) { ... }
}

public class NiceFoo : IFoo
{
    public object Flurp(IEnumerable enumerable) { ... }
}

どちらも「新しい」規則の下では合法ですよね?しかし、これはどうですか:

public class QuestionableFoo : IFoo
{
    public double Flurp(Array array) { ... }
    public object Flurp(IEnumerable enumerable) { ... }
}

ここでは、どの暗黙の実装が優れているかを判断するのは難しいです。最初のものは引数の型と完全に一致しますが、戻り値の型とは一致しません。2 番目は、戻り値の型が完全に一致しますが、引数の型は一致しません。IFooインターフェイスを使用する人は誰でもArray.

そして、これは決して最悪ではありません。代わりにこれを行うとどうなりますか:

public class EvilFoo : IFoo
{
    public object Flurp(ICollection collection) { ... }
    public object Flurp(ICloneable cloneable) { ... }
}

賞金を獲得するのはどっち?これは完全に有効なオーバーロードですがICollectionICloneable互いに何の関係もなく、Array両方を実装しています。ここには明らかな解決策はありません。

インターフェイス自体にオーバーロードを追加し始めると、さらに悪化します。

public interface ISuck
{
    Stream Munge(ArrayList list);
    Stream Munge(Hashtable ht);
    string Munge(NameValueCollection nvc);
    object Munge(IEnumerable enumerable);
}

public class HateHateHate : ISuck
{
    public FileStream Munge(ICollection collection);
    public NetworkStream Munge(IEnumerable enumerable);
    public MemoryStream Munge(Hashtable ht);
    public Stream Munge(ICloneable cloneable);
    public object Munge(object o);
    public Stream Munge(IDictionary dic);
}

気が狂わずにこの謎を解き明かそうと頑張ってください。

もちろん、インターフェイスの実装が戻り値の型の差異のみをサポートし、引数の型の差異はサポートしないと主張する場合、これはすべて意味がありません。しかし、ほとんどの人は、そのような半分の実装は完全に壊れていると見なし、バグ レポートを大量に送信し始めるので、C# チームがそれを行うとは思いません。

これが今日の C# でサポートされていない公式の理由かどうかはわかりませんが、これは、「書き込み専用」コードの種類の良い例として役立つはずであり、C# チームの設計の一部です。哲学は、開発者がひどいコードを書かないようにすることです。

于 2010-03-23T19:33:44.670 に答える
2

インターフェースのメソッドは、インターフェースにあるのとまったく同じように実装する必要があります。ICloneable の Clone メソッドはオブジェクトを返すため、SomeClass もオブジェクトを返す必要があります。ただし、問題なく SomeClass の Clone メソッドで SomeClass インスタンスを返すことはできますが、メソッド定義はインターフェイスと一致する必要があります。

public class SomeClass: IClonable
 {
     // Some Code

     //Implementing interface method
     Public object Clone()
      {
        SomeClass ret = new SomeClass();
        // copy date from this instance to ret
        return ret;
      }
 }
于 2010-03-23T17:49:48.000 に答える
1

C# の決定の背後にある理由を説明するという点では、Microsoft の Eric Lippert が C# のContra /CoVariance について多くの説明を書いています。 共分散+および+反分散/default.aspx

[編集] あなたの質問に固有の、これは正しい投稿かもしれません..インターフェイス分散.aspx

于 2010-03-23T17:51:05.853 に答える
0

C# 仕様によると、インターフェイス メソッドをオーバーライドまたは実装するときは、同じシグネチャを持つメソッドを使用する必要があります。Microsoft は C# を所有していないことに注意してください。彼らの C# コンパイラは、単にそれを実装したものです。では、なぜ仕様はこのようにするのでしょうか? 推測することしかできませんが、実装を容易にするためだったと思います。

于 2010-03-23T17:50:59.213 に答える
0

ジェネリックを使用できたようなものに見えますが、使用しなかったのには十分な理由があるようです。

それはここで話されています:

http://bytes.com/topic/c-sharp/answers/469671-generic-icloneable

基本的に、以下を可能にする汎用インターフェース: public class MyClass : IClonable<MyClass>

次のことも許可します。 public class MyClass : IClonable<MyOtherClass>

これは実際には何の利益ももたらさず、物事を混乱させる可能性があります。

于 2010-03-23T17:53:20.000 に答える