3

私はこのコードを持っています (これはうまくいくと思いますが、失敗します)。理由は本当にわかりません。助けてください

     static void Main(string[] args)
    {
        var x = new MyKeyedCollection();

        x.Add(new MyType() { Key = 400L, Value = 0.1 });
        x.Add(new MyType() { Key = 200L, Value = 0.1 });
        x.Add(new MyType() { Key = 100L, Value = 0.1 });
        x.Add(new MyType() { Key = 300L, Value = 0.1 });

        //foreach (var item in x)
        for (int i = 0; i < x.Count; i++)
        {
            //Debug.WriteLine(item.PriceLevel);
            Debug.WriteLine(x[i].Key);
        }
    }
}

public class MyType 
{
    public long Key;
    public double Value;
}

public class MyKeyedCollection : KeyedCollection<long, MyType>
{
    protected override long GetKeyForItem(MyType item)
    {
        return item.Key;
    }
}

例外:

System.Collections.Generic.KeyNotFoundException は処理
されませんでした Message=指定されたキーはディクショナリに存在しませんでした。
ソース = mscorlib StackTrace: System.Collections.Generic.Dictionary 2.get_Item(TKey key) at System.Collections.ObjectModel.KeyedCollection2の System.ThrowHelper.ThrowKeyNotFoundException() で。 get_Item(TKey キー) で KeyedCollectionTest.Program.Main(String[] args) で ...\Program.cs:line 25 で System.AppDomain._nExecuteAssembly (アセンブリ アセンブリ、String[] 引数) で Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() で System.Threading.ExecutionContext.Run (ExecutionContext executionContext、ContextCallback コールバック、オブジェクト状態) で System.Threading .ThreadHelper.ThreadStart() InnerException:

インデックスではなくキーを取得しようとするのはなぜですか? キーは明らかに長く、int ではありません。以前に KeyedCollection を使用したことは確かですが、長いキーと int インデックスに対しては問題なく機能しました。

ver2、3.5、4、4.5(VS2012使用)でコンパイルしてみました...

それを取得しないでください。

4

4 に答える 4

7

インデックスではなくキーを取得しようとするのはなぜですか? キーは明らかに長く、int ではありません。

しかし、intに変換可能longであるため、有効な候補メンバーです。

問題は、this[TKey key]インデクサーが最初に で宣言されてKeyedCollectionいるのに対し、this[int index]インデクサーは最初に で宣言されていることCollectionです。オーバーロード解決の規則では、最も派生したクラスが最初に検索され、その型で最初に宣言されたメンバーのみが開始と見なされることが指定されています。その検索が失敗した場合にのみ、コンパイラは型階層の次のレベルに移動します。

したがって、次のように書くと:

Collection<MyType> collection = x;
for (int i = 0; i < x.Count; i++)
{
    Debug.WriteLine(collection[i].Key);
}

のコンパイル時の型collectionは justCollection<T>であり、「int index」インデクサーしかないため、機能します。

ジェネリック、インデクサー、または抽象クラスを使用せずに同じ動作を示す例を次に示します。

using System;

class Base
{
    public void Foo(int x)
    {
        Console.WriteLine("Base.Foo(int)");
    }
}

class Derived : Base
{
    public void Foo(long y)
    {
        Console.WriteLine("Derived.Foo(long)");
    }
}

class Program
{
    static void Main()
    {
        Derived x = new Derived();
        Base y = x;
        x.Foo(5); // Derived.Foo(long)
        y.Foo(5); // Base.Foo(int)
    }
}

関連する興味深いルールについては、オーバーロードに関する私の記事を参照してください。

于 2013-01-15T20:52:59.407 に答える
0

単純に使用することもできます:

Debug.WriteLine(x.ElementAt(i).Key);

「ElementAt」を使用すると、指定したインデックスの要素を取得できます。これは、キーが int 型の場合にうまく機能します。

于 2013-03-27T18:55:03.163 に答える
0
class Program
{
    static void Main(string[] args)
    {
        var x = new MyKeyedCollection();

        x.Add(new MyType() { Key = 110L, Value = 0.1 });
        x.Add(new MyType() { Key = 122L, Value = 0.1 });
        x.Add(new MyType() { Key = 233L, Value = 0.1 });
        x.Add(new MyType() { Key = 344L, Value = 0.1 });

        foreach(int key in x.Keys())
        {   
            Console.WriteLine(x[key].Key);
        }

        Console.Read();
    }
}

public class MyType
{
    public long Key;
    public double Value;
}

public class MyKeyedCollection : KeyedCollection<long, MyType>
{
    protected override long GetKeyForItem(MyType item)
    {
        return item.Key;
    }

    public IEnumerable<long> Keys()
    {
        foreach (MyType item in this.Items)
        {
            yield return GetKeyForItem(item);
        }
    }
}

ここでキーを反復処理する方法で問題が解決しないでしょうか、それとも何か不足していますか?

于 2013-01-16T12:10:22.593 に答える