3

私は、彼らが作成したクレイジーな状況でのインターフェースの使用法を誰かに見せようとしています. リストには関連のないオブジェクトがいくつかあり、各オブジェクトの 2 つの文字列プロパティに対して操作を実行する必要があります。プロパティをインターフェイスの一部として定義すると、インターフェイス オブジェクトを、それに作用するメソッド パラメーターの型として使用できることを指摘しておきます。例えば:

void PrintProperties(IEnumerable<ISpecialProperties> list)
{
    foreach (var item in list)
    {
        Console.WriteLine("{0} {1}", item.Prop1, item.Prop2);
    }
}

これで問題ないように思えますが、作業が必要なリストは、インターフェイスを型パラメーターとして宣言する必要はありません (すべきではありません)。ただし、別の型パラメーターにキャストできるようには見えません。たとえば、これは失敗し、その理由がわかりません:

using System;
using System.Collections.Generic;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Test> myList = new List<Test>();
            for (int i = 0; i < 5; i++)
            {
                myList.Add(new Test());
            }

            PrintList((IEnumerable<IDoSomething>)myList);
        }

        static void PrintList(IEnumerable<IDoSomething> list)
        {
            foreach (IDoSomething item in list)
            {
                item.DoSomething();
            }
        }
    }

    interface IDoSomething
    {
        void DoSomething();
    }

    public class Test : IDoSomething
    {
        public void DoSomething()
        {
            Console.WriteLine("Test did it!");
        }
    }
}

メンバーを使用してこれを行うことができEnumerable.Cast<T>ますが、.NET 2.0 でも機能するメソッドを探していました。これは可能であるように思われます。私は何が欠けていますか?

4

5 に答える 5

5

問題はメソッドにあり、それがどのように呼び出されるかではありません.....

void PrintProperties<SP>(IEnumerable<SP> list) where SP: ISpecialProperties
{
    foreach (var item in list)
    {
        Console.WriteLine("{0} {1}", item.Prop1, item.Prop2);
    }
}
于 2008-10-09T19:23:35.027 に答える
5

失敗する理由は、ジェネリックが C# で (まだ) 差異を示さないためです。

ただし、IEnumerable<T> の修正に関しては、これを試してください。

public static IEnumerable<TBase> SafeConvert<TBase, TDerived>(IEnumerable<TDerived> source)
    where TDerived : TBase
{
    foreach (TDerived element in source)
    {
        yield return element; // Implicit conversion to TBase
    }
}

編集:この特定のケースでは、他の既存の回答の方が上記よりも優れていますが、実際にシーケンスを「変換」する必要がある場合は、一般的に役立つものとしてここに残します。

于 2008-10-09T19:26:02.573 に答える
1

foreach持っているリストでa を使用するだけです。foreach組み込みのキャストを行います。したがって、関数からループを取り除くと、次のように書くことができます

List<Test> myList = new List<Test>();
for (int i = 0; i < 5; i++)
{
   myList.Add(new Test());
}

foreach (IDoSomething item in myList)
{
   item.DoSomething();
}
于 2008-10-09T19:28:09.917 に答える
1

あなたが望むものは「インターフェース共分散」と呼ばれ、現時点ではC#ではサポートされていません。これについては、 Eric Lippert のブログで読むことができます。

于 2008-10-09T20:34:25.430 に答える
-1

これはあなたの質問 (または私が推測する演習のポイント:) には答えませんが、この場合、関心のあるプロパティに特別な属性を付加することでリフレクションを使用します。

于 2008-10-09T19:29:22.660 に答える