4

あなたがこれを持っていると仮定します:

// General purpose
public interface ISerializer
{
    IDataResult Serialize<T>(T instance);
}

// General purpose
public interface IDataResult
{
}

// Specific - and I implement IDataResult
public interface IMyCrazyDataResult : IDataResult
{
}

public class MyCrazySerializer : ISerializer
{
    // COMPILE ERROR:
    // error CS0738: 'MyCrazySerializer' does not implement interface member 'ISerializer.Serialize<T>(T)'. 
    // 'MyCrazySerializer.Serialize<T>(T)' cannot implement 'ISerializer.Serialize<T>(T)' because it does 
    // not have the matching return type of 'IDataResult'.
    public IMyCrazyDataResult Serialize<T>(T instance)
    {
        throw new NotImplementedException();
    }
}

なぜこのコンパイルエラーが発生するのですか? 私はインターフェイスを尊重しています - 実際には、間接的ではありますが IDataResult を返します。コンパイラがそれを理解できないということですか、それとも根本的に (OO レベルで) 何か間違っているのでしょうか?

インターフェイスを持つことの全体的なポイントは、何らかの実装を保証できることであると考えていましたが、それをアドオンできるように開いたままにしておきます。それが私がやっていることですが、コンパイルエラーが発生します。

実際のコードでは、派生インターフェイスにいくつかの追加メソッドがあるため、戻り値の型をもう少し具体的にしたいと考えています。IDataResult 型の MyCrazySerializer.Serialize の戻り値の型を作成すると、intellisense は私と、より具体的なインターフェイスを表示したい基本的な共通メソッドを表示するだけです。

他にどうすればこれを達成できますか? このコードの何が問題なのですか???

4

5 に答える 5

5

C#はリターン型の共分散をサポートしていないため、インターフェイスに表示されるとおりにメソッドを実装する必要がありSerialize<T>ます。ただし、明示的に実装することもできます。つまり、実際のタイプを知っているクライアントはMyCrazySerializer、より具体的なメソッドにアクセスできます。

public class MyCrazySerializer : ISerializer
{
    public IMyCrazyDataResult Serialize<T>(T instance)
    {
        throw new NotImplementedException();
    }

    IDataResult ISerializer.Serialize<T>(T instance)
    {
        return this.Serialize(instance);
    }
}

コメントが指摘しているように、明示的な実装では、より具体的なバージョンを呼び出すことができます。

次のように使用できます。

IMyCrazyDataResult result = new MyCrazySerializer().Serialize<int>(1);
ISerializer serializer = (ISerializer)new MyCrazySerializer();
IDataResult = serializer.Serialize<int>(1);
于 2012-07-21T19:26:27.613 に答える
5

C#で独自の種類のリターン型共分散を構築できます。

// General purpose
public interface ISerializer<out TResult> where TResult : IDataResult
{
    TResult Serialize<T>(T instance);
}

// General purpose
public interface IDataResult
{
}

// Specific - and I implement IDataResult
public interface IMyCrazyDataResult : IDataResult
{
}

public class MyCrazySerializer : ISerializer<IMyCrazyDataResult>
{
    public IMyCrazyDataResult Serialize<T>(T instance)
    {
        throw new NotImplementedException();
    }
}

の戻りタイプは、正確にではなく、Serializeから派生したものであると明示的に記述されています。IDataResultTResult

于 2012-07-21T19:28:34.577 に答える
3

メソッドの戻り型として別のものを指定するため、インターフェースコントラクトを満たしていないため、シグネチャは完全に一致する必要があります。これは、より指定されたインターフェースを返すことができないという意味ではありません。以下は完全に問題ありません。

// General purpose
public interface ISerializer
{
    IDataResult Serialize<T>(T instance);
}

// General purpose
public interface IDataResult
{
}

// Specific - and I implement IDataResult
public interface IMyCrazyDataResult : IDataResult
{
}

public class MyCrazySerializer : ISerializer
{
    public IDataResult Serialize<T>(T instance)
    {
        // return a IMyCrazyDataResult here
    }
}
于 2012-07-21T19:26:12.320 に答える
3

なぜこのコンパイルエラーが発生するのですか? 私はインターフェースを尊重しています

いいえ、違います。を返すのIDataResultではなく、 を返しIMyCrazyDataResultます。はい、から継承していますが、同一IDataResultはありません。

インターフェイスに関しては、差異はありません。型は正確に一致する必要があります。

于 2012-07-21T19:24:53.067 に答える
1

C ++とは異なり、C#には共変の戻り型はありません。

于 2012-07-21T19:26:20.773 に答える