IEnumerator IEnumerable.GetEnumerator() { Contract.Ensures(Contract.Result <IEnumerator>() != null); Contract.EndContractBlock(); BCLDebug.Perf(false, "Avoid using String's CharEnumerator until C# special cases foreach on String - use the indexed property on String instead."); return(new CharEnumerator(this)); }
/*=================================GetHashCode================================== **Action: Our algorithm for returning the hashcode is a little bit complex. We look ** for the first non-static field and get it's hashcode. If the type has no ** non-static fields, we return the hashcode of the type. We can't take the ** hashcode of a static member because if that member is of the same type as ** the original type, we'll end up in an infinite loop. **Returns: The hashcode for the type. **Arguments: None. **Exceptions: None. ** ==============================================================================*/ /// <include file='doc\ValueType.uex' path='docs/doc[@for="ValueType.GetHashCode"]/*' /> public override int GetHashCode() { // Note that for correctness, we can't use any field of the value type // since that field may be mutable in some way. If we use that field // and the value changes, we may not be able to look up that type in a // hash table. For correctness, we need to use something unique to // the type of this object. // HOWEVER, we decided that the perf of returning a constant value (such as // the hash code for the type) would be too big of a perf hit. We're willing // to deal with less than perfect results, and people should still be // encouraged to override GetHashCode. BCLDebug.Correctness(!(this is System.Collections.DictionaryEntry), "Calling GetHashCode on DictionaryEntry is dumb and probably wrong."); BCLDebug.Perf(false, "ValueType::GetHashCode is not fast. Perhaps " + this.GetType().FullName + " should override GetHashCode()"); RuntimeType thisType = (RuntimeType)this.GetType(); FieldInfo[] thisFields = thisType.InternalGetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, false); if (thisFields.Length > 0) { for (int i = 0; i < thisFields.Length; i++) { Object obj = ((Object)(((RuntimeFieldInfo)thisFields[i]).InternalGetValue((Object)this, false))); if (obj != null) { return(obj.GetHashCode()); } } } // Using the method table pointer is about 4x faster than getting the // sync block index for the Type object. return(GetMethodTablePtrAsInt(this)); }
public override bool Equals(Object obj) { BCLDebug.Perf(false, "ValueType::Equals is not fast. " + this.GetType().FullName + " should override Equals(Object)"); if (null == obj) { return(false); } RuntimeType thisType = (RuntimeType)this.GetType(); RuntimeType thatType = (RuntimeType)obj.GetType(); if (thatType != thisType) { return(false); } Object thisObj = (Object)this; Object thisResult, thatResult; // if there are no GC references in this object we can avoid reflection // and do a fast memcmp if (CanCompareBits(this)) { return(FastEqualsCheck(thisObj, obj)); } FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int i = 0; i < thisFields.Length; i++) { thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj); thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj); if (thisResult == null) { if (thatResult != null) { return(false); } } else if (!thisResult.Equals(thatResult)) { return(false); } } return(true); }
IEnumerator IEnumerable.GetEnumerator() { BCLDebug.Perf(false, "Avoid using String's CharEnumerator until C# special cases foreach on String - use the indexed property on String instead."); return(new CharEnumerator(this)); }