21
public abstract class EntityBase { ... }

public interface IFoobar
{
    void Foo<T>(int x)
        where T : EntityBase, new();
}

public interface IFoobar<T>
    where T : EntityBase, new()
{
    void Foo(int x);
}

public class Foobar<T> : IFoobar, IFoobar<T>
    where T : EntityBase, new()
{
    public void Foo(int x) { ... }

    void IFoobar.Foo<T>(int x) { Foo(x); }
}

コンパイラの警告が表示されます:Type parameter 'T' has the same name as the type parameter from outer type '...'

私はやってみました:void IFoobar.Foo<U>(int x) { Foo(x); }しかし、UとTが同じであることを保証することはできません。Foobarクラスの実装方法は、同じであることが非常に重要です。

また、次のことも試してみました。void IFoobar.Foo<U>(int x) where U : T { Foo(x); }ただし、UとTが等しいことを保証するものではなく、インターフェイスで定義されているため、制約を再定義することはできません。

4

3 に答える 3

15

最大の問題は、インターフェースが明確に定義されておらず、コードの意図と一致していないことです。

がインターフェース上に公開されていない場合T、外部コードはが存在することを知る必要さえありませんT。を受信または返すメソッドを作成するかT、タイプのプロパティを作成する必要がありますT。または、単にT完全に削除して、インターフェイスを非汎用にする必要があります。

これを強化すると、ここで2つの異なるインターフェースが必要ない理由がより明確になり、それらを調整する必要がなくなります。

をとるバージョンと非Tバージョンが必要であることが判明した場合、これを行うためのより慣用的な方法は、次の代わりにパスアラウンドすることです。TobjectT

public interface IFoo
{
    void DoSomething(object o);
    object DoSomethingElse();
}

public interface IFoo<T>
{
    void DoSomething(T item);
    T DoSomethingElse();
}

この例については、、、などIEnumerableのインターフェースを参照してください。ICollectionIList

ただし、慎重に検討してください。この最後の設計上の妥協点(汎用バージョンとオブジェクトバージョンの両方)は、常に何かが望まれることを残します。

これらのいずれかを犠牲にします。

  • 設計コントラクトを直接伝達する優れたインターフェイス設計(例外をスローしたり、間違ったタイプが渡されたときにno-opを実行した場合)
  • 型安全性とそれに伴うバグの削減(古いオブジェクトを正しく操作した場合)
于 2011-07-19T00:36:56.817 に答える
11

次の2つのいずれかを実行できます。

  1. 警告を無視して、両方のタイプをTにします。
  2. 実行時チェックを実行し、例外をスローします。

    if (typeof(T) != typeof(U)) throw Exception("Not the same type");
    

他の人が述べているように、おそらくあなたはあなたがあなたのインターフェースを設計している方法を再考する必要があります。

于 2011-07-19T01:36:36.233 に答える
3

ちょうど試して

void IFoobar.Foo<U>(int x) { Foo(x); }

もちろん、それでもそれUがと同じであることを保証するものではありませんT。コンパイル時にそれを強制することはできません。インターフェイスを実装するときは、そのルールに従う必要IFoobarがあります。そのような制限はありませんFoo<T>。そうすると、インターフェイスは実装されなくなります。 (定義上、あなたはより厳格であるが、あなたはそうではないと主張しているので)。

代わりに、実行時にチェックしてみることができますが、それは多少「不正行為」です(インターフェイスに実際に準拠していないため)。

于 2011-07-19T00:24:39.793 に答える