1

次のコードがあります

class Program
    {
        static void Main(string[] args)
        {
            List<A> aList = new List<A>();

            var aObj = new A();

            aObj.Go(aList.Cast<IB>());
        }
    }

    class A : IB
    {
        public void Go(IEnumerable<IB> interfaceList)
        {
            foreach (IB ibby in interfaceList)
            {
                Console.WriteLine("Here");
            }
        }
    }

    interface IB
    {
        void Go(IEnumerable<IB> interfaceList);
    }

}

私はもともと List を渡そうとしましたが、うまくいきませんSOから多くの支援を受けた後、IEnumerable を渡すことがオブジェクトを .ofType(IB) として取得する唯一の方法であることがわかりました。

残念ながら、私のコードでは、次の行が何千回も実行されます。

aList.Cast<IB>();

それがアルゴリズム的に(ILで)どのように実装されているか、そしてその時間順序が何であるかを誰かが知っているかどうか疑問に思っていました。

つまり、各項目をキャストするだけの foreach ループよりも速いのでしょうか、それともまさにそれを行うのでしょうか?

EDITメイン クラスは、実際のオブジェクトのリストを維持する必要があります。しかし、読者はインターフェースを通してそれらに触れることしか許されていません。

4

6 に答える 6

10

次のように変更する必要がありますGo

public void Go<T>(IEnumerable<T> interfaceList)
    where T : IB
{
    foreach (IB ibby in interfaceList)
    {
        Console.WriteLine("Here");
    }
}

そうすれば、電話しなくても大丈夫ですCast。Cast のソース コード実装はかなり単純だと思いますが、3.5 と 3.5SP1 の間で変更されたと思います。ただし、通常の反復子ブロックの方法で新しいステート マシンなどをセットアップする必要がある可能性があります。できれば避けた方が良いでしょう。

新しいメソッドはジェネリックですが、通常は型推論によって処理されるため、明示的に指定する必要はありませんT

于 2009-03-03T15:48:54.740 に答える
5

次のようにリストを宣言しないのはなぜですか。

List<IB> aList = new List<IB>();

具体的なクラスのリストを取得する必要があることは特にありますか?


その場合、リストをドメインの一部にします。IIBCollection (たとえば) のようなインターフェイスを用意し、リーダーがアクセスできるようにするメソッドを公開します。例えば:

interface IIBCollection{
    IEnumerable<IB> IBs { get; }
}

// and in your implementation you can do

IEnumerable<IB> IBs { 
    get { 
        foreach(IB ib in innerList) yield return ib; 
}}
于 2009-03-03T15:49:09.607 に答える
1

これは、各項目をキャストする foreach よりもわずかに遅い CastIterator として内部的に実装されています。

于 2009-03-03T15:49:33.693 に答える
0

Castメソッドは、リストをループして各アイテムをキャストするだけです。

リストを何千回も使用する場合は、キャストの結果をリストとして保存するだけです。

それが不可能な場合(つまり、毎回リストを変更する場合)は、のList<IB>代わりにを使用することを検討してList<A>ください。

于 2009-03-03T15:53:57.723 に答える
0

これは、C#の共分散の目的ではありませんか?あなたが何をしようとしているのかわからないので、なぜそれが何千回も何千回も実行された理由についてコメントすることはできません。

于 2009-03-03T15:54:48.250 に答える
0

2つのメソッド(キャスト拡張メソッドとキャスト付きのforループ)をベンチマークするだけでも、かなり簡単なことです。しかし、CastがEnumerableクラスの拡張メソッドであり、一般的にIEnumerablesを処理することを考えると、これはまさにその実装であると思います。最高の速度が必要な場合は、Listで特に機能する独自の拡張メソッドを実装するのが最適な場合があります(各要素をそのインデックスで取得します)。これは、イテレータのオーバーヘッドを考えるとわずかに高速です。それでも、どちらの方法もO(n)時間かかるはずなので、違いはそれほど大きくないはずです。それにもかかわらず、それはベンチマークする価値のあるものです...

于 2009-03-03T15:56:10.977 に答える