containsの方法

14973 ワード

cxiでもjavaでも、多くのタイプがcontainsの方法を持っています。その原理は何ですか?
javaの例を見てください。
http://blog.csdn.net/fwwdn/article/details/6746849
 
cciの中のcontainsには:
String.C.ontains
List(T).Conttains
Eumerable.sontins(TSource)
V ector.co ntains
Queue(T).Conttains
Eumerable.C.ontains
Collection.co ntains
HashSet(T).Contins
ICollection(T).Conttains
Aray.co ntains
IQueryable(T).Conttains
hashtable.C.ontains
ArayList.co ntains
Collection(T).Contins
Eumerable.sontins(TSource)
EnttityCollection.Contity
Stck(T).Conttains
Sorted List.C.ontains
ProptyBag.Coontains
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ちょっと待ってください。。。。。。。
 
msdnを見ましたが、これらのcontainsの原理は大きく三つに分けられています。
1,標準等しいコンパレータ
2,equals
3,hashcode
List<T>を例にとって、そのcontains方法の定義は
// System.Collections.Generic.List<T>

/// <summary>Determines whether an element is in the <see cref="T:System.Collections.Generic.List`1" />.</summary>

/// <returns>true if <paramref name="item" /> is found in the <see cref="T:System.Collections.Generic.List`1" />; otherwise, false.</returns>

/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.List`1" />. The value can be null for reference types.</param>

[__DynamicallyInvokable]

public bool Contains(T item)

{

    if (item == null)

    {

        for (int i = 0; i < this._size; i++)

        {

            if (this._items[i] == null)

            {

                return true;

            }

        }

        return false;

    }

    EqualityComparer<T> @default = EqualityComparer<T>.Default;

    for (int j = 0; j < this._size; j++)

    {

        if (@default.Equals(this._items[j], item))

        {

            return true;

        }

    }

    return false;

}
デフォルトの等価コンパレータを使った方法が見られます。EqualityComprerの定義を見てください。
http://msdn.microsoft.com/zh-cn/library/ms224763(v=vs.10).aspx
public abstract class EqualityComparer<T> : IEqualityComparer, IEqualityComparer<T>
この二つのインターフェースは二つの方法しかないです。EqualsとGetHashCodeは、しかし、EqualityComprerは抽象的なクラスです。IEqualityComprerインターフェースの二つの方法を実現し、プライベートな方法として定義しますが、IEqualityComprer<T>インターフェースの二つの方法を抽象的な方法のために実現します。
@default.EqualsはIEqualityComprer<T>インターフェースの方法ですので、Equalsの実現方法を知りたいです。ポイントはDefaultの取得にあります。それを通じてEqualsの定義が見えます。Defaultの定義を見てください。
        public static EqualityComparer<T> Default

        {

            get

            {

                EqualityComparer<T> equalityComparer = EqualityComparer<T>.defaultComparer;

                if (equalityComparer == null)

                {

                    equalityComparer = EqualityComparer<T>.CreateComparer();

                    EqualityComparer<T>.defaultComparer = equalityComparer;

                }

                return equalityComparer;

            }

        }
この中のdefault Comprerの定義:(todo volatile修饰符の定義)
private static volatile EqualityComparer<T> defaultComparer;
私たちはしばらくnullの場合、プライベートメソッドCreateComprerを呼び出します。
private static EqualityComparer<T> CreateComparer()

        {

            RuntimeType runtimeType = (RuntimeType)typeof(T);

            if (runtimeType == typeof(byte))

            {

                return (EqualityComparer<T>)new ByteEqualityComparer();

            }

            if (typeof(IEquatable<T>).IsAssignableFrom(runtimeType))

            {

                return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer<int>), runtimeType);

            }

            if (runtimeType.IsGenericType && runtimeType.GetGenericTypeDefinition() == typeof(Nullable<>))

            {

                RuntimeType runtimeType2 = (RuntimeType)runtimeType.GetGenericArguments()[0];

                if (typeof(IEquatable<>).MakeGenericType(new Type[]

                {

                    runtimeType2

                }).IsAssignableFrom(runtimeType2))

                {

                    return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer<int>), runtimeType2);

                }

            }

            if (runtimeType.IsEnum && Enum.GetUnderlyingType(runtimeType) == typeof(int))

            {

                return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer<int>), runtimeType);

            }

            return new ObjectEqualityComparer<T>();

        }
ここでは、実行時のタイプによって、異なるEqualityComprerサブクラスを実装します。ここでは最後のreturn(todo他のサブクラス)だけを見てください。Object EqualityComprer:これはinternalのクラスです。私たちは使えません。
internal class ObjectEqualityComparer<T> : EqualityComparer<T>
そして、私たちはEqualsを見つけることができます。ここには二つがあります。
        public override bool Equals(T x, T y)

        {

            if (x != null)

            {

                return y != null && x.Equals(y);

            }

            return y == null;

        }

        public override bool Equals(object obj)

        {

            ObjectEqualityComparer<T> objectEqualityComparer = obj as ObjectEqualityComparer<T>;

            return objectEqualityComparer != null;

        }
私たちが使っているのは最初のものです。ここではまたEqualsを呼び出しましたが、このEqualsは位置がよくて、Object.Equalsです。
現在の例が参照型である場合、Equals(Object)方法は参照等分性をテストし、Equals(Object)方法に対する呼び出しはReferenceEquals方法の呼び出しと同等である。参照の等価性は、比較する対象変数が同じオブジェクトを参照することを意味する。現在の例が値タイプの場合、Equals(Object) 方法のテスト値の等しい性。 
派生類は通常書き換えます。 Object.Equals(Object) 方法は値の等しい性を実現します。 さらに、タイプは通常、他のリロードを提供する。 Equals 方法の強いタイプは、通常実現により IEquatable インターフェース 呼び出し時 Equals 方法のテストが等しいかどうかは、現在のインスタンスが書き換えられているかどうかを確認してください。 Object.Equals どのように解決しますか? Equals メソッドの特定呼び出し。 そうでなければ、あなたが予想していたのとは違った等しいテストが実行されますので、方法は予期せぬ値を返します。
http://msdn.microsoft.com/zh-cn/library/bsc2ak47.aspx
追いかけた後:
public virtual bool Equals(object obj)

{

    return RuntimeHelpers.Equals(this, obj);

}
[SecuritySafeCritical]

[MethodImpl(MethodImplOptions.InternalCall)]

public new static extern bool Equals(object o1, object o2);
システムに内蔵されている種類のEquals方法はいずれも書き換えられると思います。私たちが関心を持っているのは、私たちがカスタマイズしたクラスはどうやってEqualsを使うかです。しかし、ここで外部の方法を導入し始めました。どうすればいいか分かりません。
http://blog.csdn.net/llddyy123wq/article/details/5620466
==========================================================================================================================================
この道は通れないので、タイプを変えて、HashSetを試してみて、まずcontainsの方法を見つけます。
public bool Contains(T item)

{

    if (this.m_buckets != null)

    {

        int num = this.InternalGetHashCode(item);

        for (int i = this.m_buckets[num % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)

        {

            if (this.m_slots[i].hashCode == num && this.m_comparer.Equals(this.m_slots[i].value, item))

            {

                return true;

            }

        }

    }

    return false;

}
見てみましたcomprerはIEqualityComprer<T>タイプですので、ここのEqualsは上と同じです。Equals以外に、hashsetはhashcodeと比較します。これは特別なところです。