2011-01-16 55 views
3

インターフェイスで作業する場合、プロパティまたはメソッドからの戻り値、またはメソッドからの戻り値が2つのメソッドを実装していることを確認したい場合がよくあります新しいインターフェイスを作成することなく、より多くのインターフェイスを使用できます。C#複数のインターフェイスの実装を返すメソッドとのインターフェイス

具体的なインスタンスは、メソッドがINotifyCollectionChangedもサポートするIEnumerable<SomeType>という結果になるように指定したいということです。つまり、インターフェイスを使用する別のオブジェクトは型キャストする必要がなく、両方の設定にアクセスできます。 (私はReadOnlyObservableCollectionを明示的に使用したくないのは、ObservableCollectionオブジェクトでしかうまくいきませんが、私が望むのであれば、インターフェイスの将来の実装者のためにオプションを開いたままにしておきたいからです。)

私は、これが唯一の方法に対するパラメータで扱うことができることを考えて、mは、次のようにメソッドの宣言を提供することで、値を返さない:

void SetStringData<T>(T data) where T : IEnumerable<string>, INotifyCollectionChanged 

をただ明確にするために、私が本当に欲しいことはどこ使ってクラスのものです正確な戻り値の型は指定できません。以下に似ていますが、明らかに構文が機能しない、あるいは理にかなっています。

(IEnumerable<string>, INotifyCollectionChanged) GetStringData() 

どのように私はこれを行うことができますか?それとも、失敗しても、私はどのように同じ結果を達成できますか?

答えて

2

ない良い解決策にはいくつかの制限を追加、しかし、私の最高の推測では、インターフェイスへのコードの契約を追加しています。依然として、呼び出し側が必要とするインターフェイスに結果をキャストする必要があります。

ような何か:

Contract.Ensures(Contract.Result<object>() is IEnumerable<string>); 
Contract.Ensures(Contract.Result<object>() is INotifyCollectionChanged); 
+0

ええと、私は本当にこれが好きです - 私はクラスでこれを行う方法を認識していました。しかし、 'ContractClassAttribute'(http://stackoverflow.com/questions/2150983)で私はそれをインターフェース上で指定することができます。ありがとう! (私はまだC#標準に明示的な解決策を追加してほしいと思っています...) –

0

おそらく一般的な方法がありますか?

T GetStringData<T>() 

そしてT

+0

これは、発信者がタイプ「T」を知ることを必要とします。したがって、 "use classは正確な戻り値の型を指定できません"という条件を満たしていません。 – CodesInChaos

+0

その場合:いいえ、できません。呼び出し元コードは、オブジェクトや別の基底クラスでOKでない限り、返される内容を知っていなければなりません。 –

2

そのすべてが実行時に解決として、私はこれが行われて見ることができる唯一の方法はdynamicのを利用しているが、例えば:

public dynamic GetStringData() 
{ 

} 

そして:

IDisposable disposable = GetStringData(); 
ISomeOtherInterface other = GetStringData(); 

BUTあなたはすべてのタイプを失うコンパイラが落ちるという安全性。私はこれを行う最善の方法は、複合インターフェイスを作るですだと思う。

public IComposite GetStringData() 
{ 

} 

そして:

IEnumerable<string> enumerable = GetStringData(); 
+0

これはすべての型安全性を失います - 単にIEnumerable を明示的に返し、 'INotifyCollectionChanged'をテストさせます。それでも、考え抜かれた答えに対して+1。ありがとう! –

0

あなたはメソッドが返すされるオブジェクトの具体的な種類について何を知っていますか?インターフェースからのリターンがウィジェットであり、そのウィジェットがIEnumerableとINotifyCollectionChangedをサポートしていることを知っている場合、ウィジェットを返す関数を定義することができます。戻り値の型が指定された目的のために設計されているクラスであることは分かっていますが、どのクラスになるのか正確には分からない場合は、IEnumerableとINotifyCollectionChangedの両方から派生する新しいインターフェイスINotifiableEnumerableを定義できます。 INotifiableEnumerableを実装して戻すクラスがあります。後者の場合、関数がIEnumerableとINotifyCollectionChangedの両方を実装していても、明示的にINotifiableEnumerableを実装していないクラスを返すことはできません。

+0

残念ながら、私は明示的に、既存のクラス、すなわち 'ReadOnlyObservableCollection'を返すことができるだけでなく、' ObservableCollection'に縛られていない同様のオブジェクトを許可したいと考えています。他の基本クラスやインターフェースがあれば、それを使っていただろう...しかし、それはなぜ私が質問したのかということです。答える時間をとってくれてありがとう! –

1

戻り値をキャッシュする別の抽象化(アダプタ)を作成し、必要な種類ごとに別々のアクセサを用意することができます。このようにして、クライアントコードはテストとキャストから保護されます。元の戻り値の代わりにこのアダプターを戻すことができます。

または、お望みの出力でtupleを返すことができます。

+0

ええと、それは私に型安全性を与え、単純なラッパーを書くことによって以前のクラスを許可します。なぜ私は以前にそれについて考えなかったのだろうか。残念ながら、これは使いやすさがある限りはちょっと鈍いと感じています...次回私がそのような要件を実装していることを覚えておきます。ありがとう! –

+0

これを踏まえて、私は、私が示唆していることは特殊なタプルであることを認識するようになりました。私はその答えを更新します。 –

関連する問題