{"id":266986,"date":"2015-10-28T16:19:04","date_gmt":"2015-10-28T13:19:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=266986"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=266986","title":{"rendered":"\u0421\u0440\u0430\u0432\u043d\u0438 \u043c\u0435\u043d\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e. \u0420\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044f \u043d\u0430 \u0441\u043b\u0443\u0436\u0431\u0435 .NET \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430"},"content":{"rendered":"<p>       <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/028\/1fa\/7c0\/0281fa7c0f364af7bd6fce4cc3b751de.jpg\" align=\"left\"\/> <\/p>\n<p>  \u041d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u043e \u043c\u043d\u043e\u0439 \u0432\u0441\u0442\u0430\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u041d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u044e\u0430\u043d\u0441: \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u2014 \u0441\u0430\u043c\u044b\u0435 \u0447\u0442\u043e \u043d\u0438 \u043d\u0430 \u0435\u0441\u0442\u044c <code>object<\/code>&#8216;\u044b, \u0430 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u043e \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u043d\u0430\u0431\u043e\u0440\u0443 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432. \u041f\u0440\u0438\u0447\u0451\u043c \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e \u0442\u0438\u043f\u044b \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms131187(v=vs.110).aspx\"><code>IEquatable&lt;T&gt;<\/code><\/a>. <\/p>\n<p>  \u0411\u044b\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044e. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u043e\u043d\u043a\u043e\u0441\u0442\u0435\u0439 \u0438 \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0441\u0447\u0451\u0442\u0435 \u043f\u0440\u0438\u0431\u0435\u0433\u043d\u0443\u043b \u043a <s>\u0447\u0451\u0440\u043d\u043e\u0439 \u043c\u0430\u0433\u0438\u0438<\/s> \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 IL. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043e\u043f\u044b\u0442\u043e\u043c \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044f \u0440\u0435\u0448\u0430\u043b \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443. \u0415\u0441\u043b\u0438 \u0412\u0430\u0441 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u0430 \u0442\u0435\u043c\u0430, \u0442\u043e \u043f\u0440\u043e\u0448\u0443 \u043f\u043e\u0434 \u043a\u0430\u0442!<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h5>\u0427\u0430\u0441\u0442\u044c 1. \u041e\u0431\u044a\u0435\u043a\u0442 \u0432 \u043e\u0442\u0440\u0430\u0436\u0435\u043d\u0438\u0438<\/h5>\n<p>  <\/p>\n<blockquote><p>\u00ab\u041f\u043e\u0434\u0430\u0442\u044c \u0441\u044e\u0434\u0430 <s>MFC<\/s> IEqualityComparer!\u00bb, \u2014 \u043a\u0440\u0438\u0447\u0430\u043b \u043e\u043d, \u0442\u043e\u043f\u0430\u044f \u0432\u0441\u0435\u043c\u0438 \u0447\u0435\u0442\u044b\u0440\u044c\u043c\u044f \u043b\u0430\u043f\u0430\u043c\u0438  <\/p><\/blockquote>\n<p>  \u0412 .NET \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u043a\u043b\u0430\u0441\u0441\u044b, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms132151(v=vs.110).aspx\">IEqualityComparer&lt;T&gt;<\/a>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u0438\u0445 \u0432 \u043a\u043b\u0430\u0441\u0441\u044b \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043f\u0438\u0441\u043a\u0438 \u0438 \u0441\u043b\u043e\u0432\u0430\u0440\u0438, \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u043f\u043e\u0438\u0441\u043a\u0435. \u041c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>IEqualityComparer&lt;object&gt;<\/code>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0435\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0438. \u041d\u0430\u043f\u043e\u043c\u043d\u0438\u043c, \u0447\u0442\u043e \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0435\u0439 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b (\u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044e, \u043d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u043e\u043c\u0443 \u0441 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0435\u0439, \u043d\u0430\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0433\u043b\u0430\u0432\u043e\u0439 \u00ab\u0420\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044f \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435\u00bb \u043a\u043d\u0438\u0433\u0438 \u0414\u0436\u043e\u0437\u0435\u0444\u0430 \u0438 \u0411\u0435\u043d\u0430 \u0410\u043b\u0431\u0430\u0445\u0430\u0440\u0438 <a href=\"http:\/\/www.williamspublishing.com\/Books\/978-5-8459-1819-2.html\">\u00abC# 5.0. \u0421\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a. \u041f\u043e\u043b\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044f\u0437\u044b\u043a\u0430\u00bb<\/a>). <\/p>\n<pre><code>public class ReflectionComparer : IEqualityComparer&lt;object&gt; {     public new bool Equals(object x, object y)     {         public new bool Equals(object x, object y)         {             return CompareObjectsInternal(x?.GetType(), x, y);         }     }      public int GetHashCode(object obj)     {         return obj.GetHashCode();     }          private bool CompareObjectsInternal(Type type, object x, object y)     {         throw new NotImplementedException();     } } <\/code><\/pre>\n<p>  \u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u043c\u0435\u0442\u043e\u0434 <code>Equals<\/code> \u043c\u044b \u043e\u0442\u043c\u0435\u0442\u0438\u043b\u0438 \u043a\u0430\u043a <code>new<\/code>. \u042d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043e\u043d \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 <code>Object.Equals(object, object)<\/code>.<\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0448\u0430\u0433 \u043d\u0430\u0437\u0430\u0434 \u0438 \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c. \u041e\u0431\u044a\u0435\u043a\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043a\u043e\u043b\u044c \u0443\u0433\u043e\u0434\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u043c\u0438, \u0432\u0441\u0451 \u043d\u0443\u0436\u043d\u043e \u0443\u0447\u0435\u0441\u0442\u044c. \u041a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u0443\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0438\u043f\u044b \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043a\u0440\u044b\u0442\u044c \u0448\u0438\u0440\u043e\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<ul>\n<li>\u0432\u0441\u0435 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b (Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, Single);<\/li>\n<li>\u0441\u0442\u0440\u043e\u043a\u0438;<\/li>\n<li>\u043c\u0430\u0441\u0441\u0438\u0432\u044b (\u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e\u043c\u0435\u0440\u043d\u044b\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u044b);<\/li>\n<li>\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f;<\/li>\n<li>\u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IEnumerable&lt;T&gt;;<\/li>\n<li>\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b;<\/li>\n<li>\u043a\u043b\u0430\u0441\u0441\u044b.<\/li>\n<\/ul>\n<p>  \u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043a\u0430\u0440\u043a\u0430\u0441 \u043c\u0435\u0442\u043e\u0434\u0430 <code>CompareObjectsInternal<\/code>, \u0430 \u0437\u0430\u0442\u0435\u043c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0447\u0430\u0441\u0442\u043d\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438.<\/p>\n<pre><code>private bool CompareObjectsInternal(Type type, object x, object y) {     \/\/ \u0415\u0441\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442     if (ReferenceEquals(x, y)) return true;      \/\/ \u041e\u0434\u0438\u043d \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0440\u0430\u0432\u0435\u043d null     if (ReferenceEquals(x, null) != ReferenceEquals(y, null)) return false;      \/\/ \u041e\u0431\u044a\u0435\u043a\u0442\u044b \u0438\u043c\u0435\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0438\u043f\u044b     if (x.GetType() != y.GetType()) return false;      \/\/ \u0421\u0442\u0440\u043e\u043a\u0438     if (Type.GetTypeCode(type) == TypeCode.String)  return ((string)x).Equals((string)y);      \/\/ \u041c\u0430\u0441\u0441\u0438\u0432\u044b     if (type.IsArray) return CompareArrays(type, x, y);          \/\/ \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438     if (type.IsImplementIEnumerable()) return CompareEnumerables(type, x, y);      \/\/ \u0421\u0441\u044b\u043b\u043e\u0447\u043d\u044b\u0435 \u0442\u0438\u043f\u044b     if (type.IsClass || type.IsInterface) return CompareAllProperties(type, x, y);      \/\/ \u041f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0438\u043b\u0438 \u0442\u0438\u043f\u044b \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439      if (type.IsPrimitive || type.IsEnum) return x.Equals(y);      \/\/ \u041e\u0431\u043d\u0443\u043b\u044f\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b     if (type.IsNullable()) return CompareNullables(type, x, y);      \/\/ \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b     if (type.IsValueType) return CompareAllProperties(type, x, y);      return x.Equals(y); } <\/code><\/pre>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435 \u043a\u043e\u0434 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u0435\u043d: \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430 \u0441\u0441\u044b\u043b\u043e\u0447\u043d\u043e\u0435 \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u043e \u0438 \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u043e <code>null<\/code>, \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u0438\u043f\u044b, \u0430 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438. \u041f\u0440\u0438\u0447\u0451\u043c \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a, \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0438 \u0442\u0438\u043f\u043e\u0432 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u043c\u044b, \u043d\u0435 \u043c\u0443\u0434\u0440\u0441\u0442\u0432\u0443\u044f \u043b\u0443\u043a\u0430\u0432\u043e, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>Equals<\/code>. \u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 \u043d\u0430 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u043a \u043e\u0431\u043d\u0443\u043b\u044f\u0435\u043c\u044b\u043c \u0442\u0438\u043f\u0430\u043c \u0438 \u0442\u0438\u043f\u0430\u043c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f <code>IsNullable<\/code> \u0438 <code>IsImplementIEnumerable<\/code>, \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0438\u0436\u0435.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u0434 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>public static bool IsImplementIEnumerable(this Type type)  =&gt; type.GetInterface(&quot;IEnumerable`1&quot;) != null; public static Type GetIEnumerableInterface(this Type type) =&gt; type.GetInterface(&quot;IEnumerable`1&quot;); public static bool IsNullable(this Type type) =&gt; type.IsGenericType && type.GetGenericTypeDefinition() == typeof (Nullable&lt;&gt;); <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u043c\u044b \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430. \u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0442\u043e\u0440\u044b \u0432 .NET \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u043e\u0434\u043d\u0430\u043a\u043e \u043c\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043c\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 (parameterless) \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438, \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0438 \u0433\u0435\u0442\u0442\u0435\u0440\u044b, \u0430 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.propertyinfo.getindexparameters(v=vs.110).aspx\">PropertyInfo.GetIndexParameters<\/a>. \u0415\u0441\u043b\u0438 \u043c\u0435\u0442\u043e\u0434 \u0432\u0435\u0440\u043d\u0443\u043b \u043c\u0430\u0441\u0441\u0438\u0432 \u043d\u0435\u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u0434\u043b\u0438\u043d\u044b, \u0437\u043d\u0430\u0447\u0438\u0442 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u0435\u043b\u043e \u0441 \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0442\u043e\u0440\u043e\u043c. <\/p>\n<pre><code>private bool CompareAllProperties(Type type, object x, object y) {     var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);     var readableNonIndexers = properties.Where(p =&gt; p.CanRead && p.GetIndexParameters().Length == 0);      foreach (PropertyInfo propertyInfo in readableNonIndexers)     {         var a = propertyInfo.GetValue(x, null);         var b = propertyInfo.GetValue(y, null);          if (!CompareObjectsInternal(propertyInfo.PropertyType, a, b)) return false;     }      return true; } <\/code><\/pre>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0435 \u2014 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 nullable-\u0442\u0438\u043f\u043e\u0432. \u0415\u0441\u043b\u0438 \u043d\u0438\u0436\u0435\u043b\u0435\u0436\u0430\u0449\u0438\u0439 \u0442\u0438\u043f \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0439, \u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>Equals<\/code>. \u0415\u0441\u043b\u0438 \u0436\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043b\u0435\u0436\u0430\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b, \u0442\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0437\u043d\u0430\u0435\u043d\u0438\u044f, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u0438\u0445 \u043f\u043e \u0432\u0441\u0435\u043c \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c. \u041c\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443 <code>Value<\/code>, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u0430 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u0440\u0430\u043d\u0435\u0435 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>CompareObjectsInternal<\/code>. <\/p>\n<pre><code>private bool CompareNullables(Type type, object x, object y) {     Type underlyingTypeOfNullableType = Nullable.GetUnderlyingType(type);      if (underlyingTypeOfNullableType.IsPrimitive)     {         return x.Equals(y);     }      var valueProperty = type.GetProperty(&quot;Value&quot;);     var a = valueProperty.GetValue(x, null);     var b = valueProperty.GetValue(y, null);      return CompareAllProperties(underlyingTypeOfNullableType, a, b); } <\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0434\u0432\u0443\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438: \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043d\u0435\u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0441 IEnumerable, \u043b\u0438\u0431\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/vstudio\/bb342073(v=vs.100).aspx\">Enumerable.SequenceEqual&lt;TSource&gt;<\/a>. \u0414\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439, \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0442\u0438\u043f-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043d\u0435\u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u0435\u0435, \u0442.\u043a. \u0435\u043c\u0443 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0443\/\u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439. \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0436\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 LINQ \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440-\u0442\u0438\u043f\u0430 TSource \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.methodinfo.makegenericmethod(v=vs.110).aspx\">MakeGenericMethod<\/a>), \u0430 \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0434\u0432\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438. \u041f\u0440\u0438\u0447\u0451\u043c, \u0435\u0441\u043b\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043d\u0435\u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u2014 \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440 \u2014 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>ReflectionComparer<\/code> (\u043d\u0435 \u0437\u0440\u044f \u0436\u0435 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>IEqualityComparer&lt;object&gt;<\/code>!). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c LINQ: <\/p>\n<pre><code>private static MethodInfo GenericSequenceEqualWithoutComparer = typeof(Enumerable)         .GetMethods(BindingFlags.Public | BindingFlags.Static)         .First(m =&gt; m.Name == &quot;SequenceEqual&quot; && m.GetParameters().Length == 2);  private static MethodInfo GenericSequenceEqualWithComparer = typeof(Enumerable)         .GetMethods(BindingFlags.Public | BindingFlags.Static)         .First(m =&gt; m.Name == &quot;SequenceEqual&quot; && m.GetParameters().Length == 3);  private bool CompareEnumerables(Type collectionType, object x, object y) {     Type enumerableInterface = collectionType.GetIEnumerableInterface();     Type elementType = enumerableInterface.GetGenericArguments()[0];      MethodInfo sequenceEqual;     object[] arguments;      if (elementType.IsPrimitive)     {         sequenceEqual = GenericSequenceEqualWithoutComparer;         arguments = new[] {x, y};     }     else     {         sequenceEqual = GenericSequenceEqualWithComparer;         arguments = new[] {x, y, this};     }      var sequenceEqualMethod = sequenceEqual.MakeGenericMethod(elementType);      return (bool)sequenceEqualMethod.Invoke(null, arguments); }        <\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u2014 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u2014 \u0432\u043e \u043c\u043d\u043e\u0433\u043e\u043c \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439. \u041e\u0442\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 LINQ \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 \u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043d\u0438\u0436\u0435:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>private static MethodInfo GenericCompareArraysMethod =     typeof(ReflectionComparer).GetMethod(&quot;GenericCompareArrays&quot;, BindingFlags.NonPublic | BindingFlags.Static);              private static bool GenericCompareArrays&lt;T&gt;(T[] x, T[] y, IEqualityComparer&lt;T&gt; comparer) {     var comp = comparer ?? EqualityComparer&lt;T&gt;.Default;      for (int i = 0; i &lt; x.Length; ++i)     {         if (!comp.Equals(x[i], y[i])) return false;     }      return true; }  private bool CompareArrays(Type type, object x, object y) {     var elementType = type.GetElementType();     int xLength, yLength;          if (elementType.IsValueType)     {         \/\/ \u041c\u0430\u0441\u0441\u0438\u0432\u044b \u0442\u0438\u043f\u043e\u0432-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u043a \u043c\u0430\u0441\u0441\u0438\u0432\u0443 object, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Array         xLength = ((Array) x).Length;         yLength = ((Array) y).Length;     }     else     {         xLength = ((object[]) x).Length;         yLength = ((object[]) y).Length;     }      if (xLength != yLength) return false;      var compareArraysPrimitive = GenericCompareArraysMethod.MakeGenericMethod(elementType);     var arguments = elementType.IsPrimitive ? new[] {x, y, null} : new[] {x, y, this};      return (bool) compareArraysPrimitive.Invoke(null, arguments); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418\u0442\u0430\u043a, \u0432\u0441\u0435 \u0447\u0430\u0441\u0442\u0438 \u043f\u0430\u0437\u043b\u0430 \u0441\u043e\u0431\u0440\u0430\u043d\u044b \u2014 \u043d\u0430\u0448 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440 \u0433\u043e\u0442\u043e\u0432. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440\u0430 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0440\u0443\u0447\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043d\u0430 \u00ab\u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445\u00bb \u0434\u0430\u043d\u043d\u044b\u0445. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f <b>\u043e\u0447\u0435\u043d\u044c<\/b> \u0441\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0437\u0434\u0435\u0441\u044c \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0434\u0432\u0443\u0445 \u0442\u0438\u043f\u043e\u0432 \u2014 \u0443\u0441\u043b\u043e\u0432\u043d\u043e \u00ab\u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435\u00bb \u0438 \u00ab\u043f\u043e\u043f\u0440\u043e\u0449\u0435\u00bb. \u0414\u043b\u044f \u043e\u0446\u0435\u043d\u043a\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0430\u0441\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/github.com\/PerfDotNet\/BenchmarkDotNet\">BenchmarkDotNet<\/a>, \u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0441\u043e\u0431\u0443\u044e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u043d\u043e\u0441\u0442\u044c \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0410\u043d\u0434\u0440\u0435\u044e \u0410\u043a\u0438\u043d\u044c\u0448\u0438\u043d\u0443  <a href=\"http:\/\/habrahabr.ru\/users\/dreamwalker\/\" class=\"user_link\">DreamWalker<\/a>.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u0434 \u0442\u0443\u0442<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>public struct Struct {     private int m_a;     private double m_b;     private string m_c;      public int A =&gt; m_a;     public double B =&gt; m_b;     public string C =&gt; m_c;      public Struct(int a, double b, string c)     {         m_a = a;         m_b = b;         m_c = c;     } }  public class SimpleClass {     public int A { get; set; }     public Struct B { get; set; } }  public class ComplexClass {     public int A { get; set; }     public IntPtr B { get; set; }     public UIntPtr C { get; set; }     public string D { get; set; }     public SimpleClass E { get; set; }     public int? F { get; set; }     public int[] G { get; set; }     public List&lt;int&gt; H { get; set; }     public double I { get; set; }     public float J { get; set; } }  [BenchmarkTask(platform: BenchmarkPlatform.X86, jitVersion: BenchmarkJitVersion.LegacyJit)] [BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.LegacyJit)] [BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.RyuJit)] public class ComparisonTest {     private static int[] MakeArray(int count)     {         var array = new int[count];          for (int i = 0; i &lt; array.Length; ++i)             array[i] = i;          return array;     }      private static List&lt;int&gt; MakeList(int count)     {         var list = new List&lt;int&gt;(count);          for (int i = 0; i &lt; list.Count; ++i)             list.Add(i);          return list;     }      private ComplexClass x = new ComplexClass     {         A = 2,         B = new IntPtr(2),         C = new UIntPtr(2),         D = &quot;abc&quot;,         E = new SimpleClass { A = 42, B = new Struct(42, 3.14, &quot;meow&quot;) },         F = 1,         G = MakeArray(100),         H = MakeList(100),         I = double.MaxValue,         J = float.MaxValue     };      private ComplexClass y = new ComplexClass     {         A = 2,         B = new IntPtr(2),         C = new UIntPtr(2),         D = &quot;abc&quot;,         E = new SimpleClass { A = 42, B = new Struct(42, 3.14, &quot;meow&quot;) },         F = 1,         G = MakeArray(100),         H = MakeList(100),         I = double.MaxValue,         J = float.MaxValue     };      private ReflectionComparer comparer = new ReflectionComparer();      [Benchmark]     public void ReflectionCompare()     {         var _ = comparer.Equals(x, y);     }      [Benchmark]     public void ManualCompare()     {         var _ = CompareComplexObjects();     }      private bool CompareComplexObjects()     {         if (x == y) return true;         if (x.A != y.A) return false;         if (x.B != y.B) return false;         if (x.C != y.C) return false;         if (x.D != y.D) return false;         if (x.E != y.E)         {             if (x.E.A != y.E.A) return false;             var s1 = x.E.B;             var s2 = y.E.B;             if (s1.A != s2.A) return false;             if (!s1.B.Equals(s2.B)) return false;             if (s1.C != s2.C) return false;         }         if (x.F != y.F) return false;         if (x.G != y.G)         {             if (x.G?.Length != y.G?.Length) return false;             int[] a = x.G, b = y.G;             for (int i = 0; i &lt; a.Length; ++i)             {                 if (a[i] != b[i]) return false;             }         }         if (x.H != y.H)         {             if (!x.H.SequenceEqual(y.H)) return false;         }         if (!x.I.Equals(y.I)) return false;         if (!x.J.Equals(y.J)) return false;         return true;     } }  [BenchmarkTask(platform: BenchmarkPlatform.X86, jitVersion: BenchmarkJitVersion.LegacyJit)] [BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.LegacyJit)] [BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.RyuJit)] public class SimpleComparisonTest {     private SimpleClass x = new SimpleClass { A = 42, B = new Struct(42, 3.14, &quot;meow&quot;) };     private SimpleClass y = new SimpleClass { A = 42, B = new Struct(42, 3.14, &quot;meow&quot;) };      private ReflectionComparer comparer = new ReflectionComparer();      [Benchmark]     public void ReflectionCompare()     {         var _ = comparer.Equals(x, y);     }      [Benchmark]     public void ManualCompare()     {         var _ = CompareSimpleObjects();     }      private bool CompareSimpleObjects()     {         if (x == y) return true;         if (x.A != y.A) return false;         var s1 = x.B;         var s2 = y.B;         if (s1.A != s2.A) return false;         if (!s1.B.Equals(s2.B)) return false;         if (s1.C != s2.C) return false;         return true;     } }     <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0443\u0442<\/b><\/p>\n<div class=\"spoiler_text\">BenchmarkDotNet=v0.7.8.0<br \/>  OS=Microsoft Windows NT 6.2.9200.0<br \/>  Processor=Intel Core(TM) i5-2410M CPU @ 2.30GHz, ProcessorCount=4<br \/>  HostCLR=MS.NET 4.0.30319.42000, Arch=64-bit [RyuJIT]<\/p>\n<p>  <b>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 ComplexClass<\/b>   <\/p>\n<table>\n<tr>\n<th>Method<\/th>\n<th>Platform<\/th>\n<th>Jit<\/th>\n<th>AvrTime<\/th>\n<th>StdDev<\/th>\n<th>op\/s<\/th>\n<\/tr>\n<tr>\n<td>ManualCompare<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>1,364.3835 ns<\/td>\n<td>47.6975 ns<\/td>\n<td>732,941.68<\/td>\n<\/tr>\n<tr>\n<td>ReflectionCompare<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>36,779.9097 ns<\/td>\n<td>3,080.9738 ns<\/td>\n<td>27,188.92<\/td>\n<\/tr>\n<tr>\n<td>ManualCompare<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>930.8761 ns<\/td>\n<td>43.6018 ns<\/td>\n<td>1,074,294.12<\/td>\n<\/tr>\n<tr>\n<td>ReflectionCompare<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>36,909.7334 ns<\/td>\n<td>3,762.0698 ns<\/td>\n<td>27,093.98<\/td>\n<\/tr>\n<tr>\n<td>ManualCompare<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>936.3367 ns<\/td>\n<td>38.3831 ns<\/td>\n<td>1,067,992.54<\/td>\n<\/tr>\n<tr>\n<td>ReflectionCompare<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>32,446.6969 ns<\/td>\n<td>1,687.8442 ns<\/td>\n<td>30,819.81<\/td>\n<\/tr>\n<\/table>\n<p>  <b>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 SimpleClass<\/b>  <\/p>\n<table>\n<tr>\n<th>Method<\/th>\n<th>Platform<\/th>\n<th>Jit<\/th>\n<th>AvrTime<\/th>\n<th>StdDev<\/th>\n<th>op\/s<\/th>\n<\/tr>\n<tr>\n<td>Handwritten<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>131.5205 ns<\/td>\n<td>4.9045 ns<\/td>\n<td>7,603,376.64<\/td>\n<\/tr>\n<tr>\n<td>ReflectionComparer<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>3,859.7102 ns<\/td>\n<td>269.8845 ns<\/td>\n<td>259,087.15<\/td>\n<\/tr>\n<tr>\n<td>Handwritten<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>61.2438 ns<\/td>\n<td>1.9025 ns<\/td>\n<td>16,328,222.24<\/td>\n<\/tr>\n<tr>\n<td>ReflectionComparer<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>3,841.4645 ns<\/td>\n<td>374.0006 ns<\/td>\n<td>260,317.46<\/td>\n<\/tr>\n<tr>\n<td>Handwritten<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>71.5982 ns<\/td>\n<td>5.4304 ns<\/td>\n<td>13,966,823.95<\/td>\n<\/tr>\n<tr>\n<td>ReflectionComparer<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>3,636.7963 ns<\/td>\n<td>241.3940 ns<\/td>\n<td>274,967.76<\/td>\n<\/tr>\n<\/table>\n<\/div>\n<\/div>\n<p>  \u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u0440\u043e\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440\u0430 \u043d\u0438\u0436\u0435 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u043e\u0433\u043e. \u0420\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044f \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0430 \u0438 \u0435\u0451 API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 <code>object<\/code>&#8216;\u0430\u043c\u0438, \u0447\u0442\u043e \u043d\u0435\u0437\u0430\u043c\u0435\u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0435\u0441\u043b\u0438 \u0432 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u0445 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0438\u043f\u044b-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0438\u0437-\u0437\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c boxing\/unboxing. \u0418 \u0442\u0443\u0442 \u0443\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0438\u0437 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0435\u0439. \u0415\u0441\u043b\u0438 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435 \u0447\u0430\u0441\u0442\u043e, \u0442\u043e \u0441 \u043d\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0436\u0438\u0442\u044c. \u041d\u043e \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440 \u0431\u044b\u043b \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u044b\u0441\u0442\u0440. \u00ab\u0414\u0430\u0432\u0430\u0439 \u043f\u043e \u043d\u043e\u0432\u043e\u0439<s>, \u041c\u0438\u0448<\/s>\u00bb, \u2014 \u0441\u043a\u0430\u0437\u0430\u043b \u044f \u0441\u0435\u0431\u0435 \u0438 \u043f\u0440\u0438\u043d\u044f\u043b\u0441\u044f \u0437\u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442.<\/p>\n<h5>\u0427\u0430\u0441\u0442\u044c 2. \u0418\u0433\u0440\u0430 \u0432 emit\u0430\u0446\u0438\u044e<\/h5>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/aa4\/555\/949\/aa4555949ff84cf0b112c33d9c47156d.jpg\"\/><\/p>\n<blockquote><p> \u041c\u043e\u0436\u043d\u043e \u0436\u0438\u0442\u044c \u0442\u0430\u043a, \u043d\u043e \u043b\u0443\u0447\u0448\u0435 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c\u0441\u044f <br \/>  <i>\u0413\u0440\u0443\u043f\u043f\u0430 \u041b\u0435\u043d\u0438\u043d\u0433\u0440\u0430\u0434, \u00ab\u041c\u043d\u0435 \u0431\u044b \u0432 \u043d\u0435\u0431\u043e\u00bb<\/i><\/p>\n<p>  \u041d\u0435\u043e: \u0418 \u0442\u044b \u044d\u0442\u043e \u0447\u0438\u0442\u0430\u0435\u0448\u044c?<br \/>  \u0421\u0430\u0439\u0444\u0435\u0440: \u041f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f. \u0421\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043f\u0440\u0438\u0432\u044b\u043a\u0430\u0435\u0448\u044c. \u042f \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u044e \u043a\u043e\u0434. \u042f \u0432\u0438\u0436\u0443 \u0431\u043b\u043e\u043d\u0434\u0438\u043d\u043a\u0443, \u0431\u0440\u044e\u043d\u0435\u0442\u043a\u0443, \u0440\u044b\u0436\u0435\u043d\u044c\u043a\u0443\u044e.<br \/>   <i>\u0424\u0438\u043b\u044c\u043c \u00ab\u041c\u0430\u0442\u0440\u0438\u0446\u0430\u00bb (The Matrix)<\/i>   <\/p><\/blockquote>\n<p>  \u0420\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0432\u0441\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u0438\u043f\u0430\u0445 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u041d\u043e \u044d\u0442\u0438 \u0442\u0438\u043f\u044b \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0443\u0436\u043d\u044b\u0445 \u043d\u0430\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0438\u043b\u0438 \u0432\u044b\u0437\u043e\u0432\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043d\u0430\u0441 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0433\u043e API \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0438 (PropertyInfo.GetValue, MethodInfo.Invoke \u0438 \u0442.\u0434.). \u0410 \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u0438\u043f\u0430\u0445, \u0435\u0434\u0438\u043d\u043e\u0436\u0434\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437, \u043d\u0435 \u043f\u0440\u0438\u0431\u0435\u0433\u0430\u044f \u0431\u043e\u043b\u0435\u0435 \u043a \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0438? \u0418, \u043a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c! \u041f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0438\u043c\u0451\u043d <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit(v=vs.110).aspx\">System.Reflection.Emit<\/a> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u2014 <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.dynamicmethod(v=vs.110).aspx\">DynamicMethod<\/a> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/Common_Intermediate_Language\">IL<\/a> \u2014 <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.ilgenerator(v=vs.110).aspx\">ILGenerator<\/a>. \u0418\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u043f\u043e\u0434\u0445\u043e\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f, \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 \u0441\u0430\u043c\u043e\u043c .NET Framework (\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"http:\/\/referencesource.microsoft.com\/#System\/regex\/system\/text\/regularexpressions\/RegexCompiler.cs\">\u0442\u0443\u0442<\/a>).<\/p>\n<p>  \u041e \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 IL \u043d\u0430 \u0425\u0430\u0431\u0440\u0435 \u0443\u0436\u0435 <a href=\"http:\/\/habrahabr.ru\/post\/172487\/\">\u043f\u0438\u0441\u0430\u043b\u0438<\/a>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043b\u0438\u0448\u044c \u0432\u043a\u0440\u0430\u0442\u0446\u0435 \u043d\u0430\u043f\u043e\u043c\u043d\u0438\u043c \u043e\u0431 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u0445 IL.<\/p>\n<p>  <a href=\"https:\/\/ru.wikipedia.org\/wiki\/Common_Intermediate_Language\">Intermediate Language (IL)<\/a> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a \u0430\u0441\u0441\u0435\u043c\u0431\u043b\u0435\u0440\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0439 .NET \u0438 Mono. \u0412\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u044f\u0437\u044b\u043a\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, C#, VB.NET, F#, \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 IL, \u0430 IL \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f JIT&#8217;\u043e\u043c \u0432 \u043c\u0430\u0448\u0438\u043d\u043d\u044b\u0439 \u043a\u043e\u0434. \u0418\u0437-\u0437\u0430 \u0441\u0432\u043e\u0435\u0433\u043e \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 \u044d\u0442\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u044f\u0437\u044b\u043a \u0438 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0451 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435. IL \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0442\u0435\u043a\u043e\u0432\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439, \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u0435\u043a, \u0430 \u043d\u0435 \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b, \u043a\u0430\u043a \u0432\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043d\u044b\u0445 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430\u0445. IL \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438, \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u0432\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<p>  \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0438\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430 IL \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>ldloc.0    \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e ldc.i4.1   \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0435\u0434\u0438\u043d\u0438\u0446\u0443 add        \/\/ \u0421\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c stloc.0    \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043a\u043e\u043c\u043f\u043b\u0438\u044f\u0446\u0438\u0438 C# \u0432 IL \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, ILDasm (\u0443\u0442\u0438\u043b\u0438\u0442\u0430, \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u0430\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 Visual Studio) \u0438\u043b\u0438 <a href=\"http:\/\/ilspy.net\/\">ILSpy<\/a>. \u041d\u043e \u043c\u043e\u0439 \u043b\u044e\u0431\u0438\u043c\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u2014 \u044d\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f <a href=\"http:\/\/tryroslyn.azurewebsites.net\/\">Try Roslyn<\/a>, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0410\u043d\u0434\u0440\u0435\u0435\u043c \u0429\u0451\u043a\u0438\u043d\u044b\u043c  <a href=\"http:\/\/habrahabr.ru\/users\/ashmind\/\" class=\"user_link\">ashmind<\/a>.<\/p>\n<p>  \u0412\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435. \u041c\u044b \u043e\u043f\u044f\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>IEqualityComparer&lt;object&gt;<\/code>:<\/p>\n<pre><code>public class DynamicCodeComparer : IEqualityComparer&lt;object&gt; {     \/\/ \u0414\u0435\u043b\u0435\u0433\u0430\u0442 \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432     private delegate bool Comparer(object x, object y);      \/\/ \u041a\u044d\u0448 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440\u043e\u0432     private static Dictionary&lt;Type, Comparer&gt; ComparerCache = new Dictionary&lt;Type, Comparer&gt;();      public new bool Equals(object x, object y)     {         \/\/ \u0415\u0441\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442         if (ReferenceEquals(x, y)) return true;          \/\/ \u041e\u0434\u0438\u043d \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0440\u0430\u0432\u0435\u043d null         if (ReferenceEquals(x, null) != ReferenceEquals(y, null)) return false;          Type xType = x.GetType();          \/\/ \u041e\u0431\u044a\u0435\u043a\u0442\u044b \u0438\u043c\u0435\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0438\u043f\u044b         if (xType != y.GetType()) return false;          \/\/         \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440\u0430 \u0432 \u043a\u044d\u0448\u0435. \u0415\u0441\u043b\u0438 \u043d\u0435\u0442, \u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0435\u0433\u043e \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 \u043a\u044d\u0448         \/\/          Comparer comparer;         if (!ComparerCache.TryGetValue(xType, out comparer))         {             ComparerCache[xType] = comparer = new ComparerDelegateGenerator().Generate(xType);         }          return comparer(x, y);     }      public int GetHashCode(object obj)     {         return obj.GetHashCode();     } } <\/code><\/pre>\n<p>  \u041c\u0435\u0442\u043e\u0434 <code>Equals<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043a\u044d\u0448\u0430 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u043e\u0432 \u2014 \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440\u043e\u0432, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0445 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440\u0430 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0435\u0449\u0451 \u043d\u0435\u0442 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0435, \u0442\u043e \u043c\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0434\u0435\u043b\u0435\u0433\u0430\u0442. \u0412\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0435\u043d\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>ComparerDelegateGenerator<\/code>. <\/p>\n<pre><code>class ComparerDelegateGenerator {     \/\/ \u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043a\u043e\u0434\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430     private ILGenerator il;      public Comparer Generate(Type type)     {         \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0432 \u0442\u043e\u043c \u0436\u0435 \u043c\u043e\u0434\u0443\u043b\u0435, \u0447\u0442\u043e \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c\u044b\u0439 \u0442\u0438\u043f         var dynamicMethod = new DynamicMethod(&quot;__DynamicCompare&quot;, typeof(bool), new[] { typeof(object), typeof(object) },                                                type.Module);          il = dynamicMethod.GetILGenerator();          \/\/         \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u043f\u0440\u0438\u043a\u0430\u0441\u0442\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0438\u0445 \u043a \u0442\u0438\u043f\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f         \/\/          il.LoadFirstArg();         var arg0 = il.CastToType(type);          il.LoadSecondArg();         var arg1 = il.CastToType(type);          \/\/ \u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b         CompareObjectsInternal(type, arg0, arg1);          \/\/ \u0415\u0441\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u0448\u043b\u043e \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430, \u0437\u043d\u0430\u0447\u0438\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0440\u0430\u0432\u043d\u044b         il.ReturnTrue();          \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430         return (Comparer)dynamicMethod.CreateDelegate(typeof(Comparer));     } } <\/code><\/pre>\n<p>  \u0412 \u043c\u0435\u0442\u043e\u0434\u0435 <code>Generate<\/code> \u0432\u044b\u0448\u0435 \u0435\u0441\u0442\u044c \u043e\u0434\u0438\u043d \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u043d\u044e\u0430\u043d\u0441. \u041d\u044e\u0430\u043d\u0441 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0432 \u0442\u043e\u043c \u0436\u0435 \u043c\u043e\u0434\u0443\u043b\u0435, \u0447\u0442\u043e \u0438 \u0442\u0438\u043f \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u043e\u0434 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0442\u0438\u043f\u0443 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 <code>TypeAccessException<\/code>. \u041a\u043b\u0430\u0441\u0441 <code>ILGenerator<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.ilgenerator.emit(v=vs.110).aspx\">Emit(OpCode)<\/a>, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0435\u0433\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043a\u043e\u0434 \u043a\u043e\u043c\u0430\u043d\u0434\u044b. \u041d\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0437\u0430\u0441\u043e\u0440\u044f\u0442\u044c \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0434\u0435\u0442\u0430\u043b\u044f\u043c\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043e\u043d\u0438 \u0434\u0435\u043b\u0430\u044e\u0442. \u041a\u043e\u0434 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f <code>LoadFirstArg, LoadSecondArg, CastToType<\/code> \u0438 <code>ReturnTrue<\/code> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043d\u0438\u0436\u0435. \u0421\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u044f\u0441\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u0432 <code>Generate<\/code> \u043c\u0435\u0442\u043e\u0434 <code>CompareObjectsInternal<\/code> \u0431\u0443\u0434\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>return false<\/code> \u0441\u0440\u0430\u0437\u0443 \u0436\u0435, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 <code>return true<\/code>, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u0430\u0442\u044c \u0442\u0443 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0440\u0430\u0432\u043d\u044b. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u0434 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>\/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0432 \u0441\u0442\u0435\u043a \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 public static void LoadFirstArg(this ILGenerator il) =&gt; il.Emit(OpCodes.Ldarg_0);  \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0432 \u0441\u0442\u0435\u043a \u0432\u0442\u043e\u0440\u043e\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 public static void LoadSecondArg(this ILGenerator il) =&gt; il.Emit(OpCodes.Ldarg_1);  \/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u0435\u0433\u043e \u043a \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0442\u0438\u043f\u0443 public static LocalBuilder CastToType(this ILGenerator il, Type type) {         var x = il.DeclareLocal(type);      \/\/ \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0442\u0438\u043f\u043e\u0432-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0443     if (type.IsValueType || type.IsPrimitive)     {         il.Emit(OpCodes.Unbox_Any, type);     }     \/\/ \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0441\u044b\u043b\u043e\u0447\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435     else     {         il.Emit(OpCodes.Castclass, type);     }      il.SetLocal(x);          return x; }  \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0432 \u0441\u0442\u0435\u043a \u043d\u043e\u043b\u044c (\u043e\u043d \u0436\u0435 false) public static void LoadZero(this ILGenerator il) =&gt; il.Emit(OpCodes.Ldc_I4_0);  \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0432 \u0441\u0442\u0435\u043a \u0435\u0434\u0438\u043d\u0438\u0446\u0443 (\u043e\u043d\u0430 \u0436\u0435 true) public static void LoadOne(this ILGenerator il) =&gt; il.Emit(OpCodes.Ldc_I4_1);  \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u0437 \u043c\u0435\u0442\u043e\u0434\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 false public static void ReturnFalse(this ILGenerator il) {     il.LoadZero();     il.Emit(OpCodes.Ret); }  \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u0437 \u043c\u0435\u0442\u043e\u0434\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 true public static void ReturnTrue(this ILGenerator il) {     il.LoadOne();     il.Emit(OpCodes.Ret); } <\/code><\/pre>\n<\/div>\n<\/div>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043c\u0435\u0442\u043e\u0434 <code>CompareObjectsInternal<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u0438\u043f\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432:<\/p>\n<pre><code>private void CompareObjectsInternal(Type type, LocalBuilder x, LocalBuilder y) {     \/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043a\u0443, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u044b\u0433\u0430\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0440\u0430\u0432\u043d\u044b     var whenEqual = il.DefineLabel();      \/\/ \u0415\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0442\u0438\u043f\u0430\u043c\u0438-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439     if (!type.IsValueType)     {         \/\/ \u0422\u0443\u0442 \u0436\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c true, \u0435\u0441\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u0440\u0430\u0432\u043d\u044b \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439         JumpIfReferenceEquals(x, y, whenEqual);          \/\/ \u0415\u0441\u043b\u0438 \u043e\u0434\u0438\u043d \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0440\u0430\u0432\u0435\u043d null, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u043d\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c false         ReturnFalseIfOneIsNull(x, y);          \/\/ \u041c\u0430\u0441\u0441\u0438\u0432\u044b         if (type.IsArray)         {             CompareArrays(type.GetElementType(), x, y);         }         \/\/ \u041a\u043b\u0430\u0441\u0441\u044b \u0438\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b         else if (type.IsClass || type.IsInterface)         {             \/\/ \u0421\u0442\u0440\u043e\u043a\u0438             if (Type.GetTypeCode(type) == TypeCode.String)             {                 CompareStrings(x, y, whenEqual);             }             \/\/ \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438             else if (type.IsImplementIEnumerable())             {                 CompareEnumerables(type, x, y);             }             \/\/ \u041b\u044e\u0431\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b             else             {                 CompareAllProperties(type, x, y);             }         }     }     \/\/ \u041e\u0431\u043d\u0443\u043b\u044f\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b     else if (type.IsNullable())     {         CompareNullableValues(type, x, y, whenEqual);     }     \/\/ \u041f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f     else if (type.IsPrimitive || type.IsEnum)     {         ComparePrimitives(type, x, y, whenEqual);     }     \/\/ \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b     else     {         CompareAllProperties(type, x, y);     }      \/\/ \u0421\u0442\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043a\u0443, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u044b\u0433\u0430\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0440\u0430\u0432\u043d\u044b     il.MarkLabel(whenEqual); } <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u043a\u043e\u0434\u0430, \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0442\u0435 \u0436\u0435 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u0447\u0442\u043e \u0438 \u0432 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0432\u043d\u043e\u043c \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440\u0435, \u043d\u043e \u0432 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u0440\u0443\u0433\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435. \u042d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441 <code>null<\/code> \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0441\u0441\u044b\u043b\u043e\u0447\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u043d\u043e \u043d\u0435 \u0434\u043b\u044f \u043e\u0431\u043d\u0443\u043b\u044f\u0435\u043c\u044b\u0445. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0431\u043d\u0443\u043b\u044f\u0435\u043c\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>HasValue<\/code>.<\/p>\n<p>  \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u0432 \u043a\u043e\u043d\u0446\u0435 \u044f \u0434\u0430\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438. \u041d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u043a\u043e\u0434 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0447\u0443\u0432\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0438\u0437 \u0441\u0435\u0431\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434.<\/p>\n<pre><code>private void CompareArrays(Type elementType, LocalBuilder x, LocalBuilder y) {     var loop = il.DefineLabel();  \/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043a\u0443 \u043d\u0430\u0447\u0430\u043b\u0430 \u0446\u0438\u043a\u043b\u0430 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432      il.LoadArrayLength(x);        \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0434\u043b\u0438\u043d\u0443 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430     il.LoadArrayLength(y);        \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0434\u043b\u0438\u043d\u0443 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430     il.JumpWhenEqual(loop);       \/\/ \u0415\u0441\u043b\u0438 \u0434\u043b\u0438\u043d\u044b \u0440\u0430\u0432\u043d\u044b, \u0442\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0446\u0438\u043a\u043b\u0443     il.ReturnFalse();             \/\/ \u0418\u043d\u0430\u0447\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c false      il.MarkLabel(loop);           \/\/ \u041e\u0442\u043c\u0435\u0447\u0430\u0435\u043c \u043c\u0435\u0442\u043a\u0443 \u043d\u0430\u0447\u0430\u043b\u0430 \u0446\u0438\u043a\u043b\u0430      var index = il.DeclareLocal(typeof(int)); \/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u0446\u0438\u043a\u043b\u0430 - \u0438\u043d\u0434\u0435\u043a\u0441     var loopCondition = il.DefineLabel();     \/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043a\u0443 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0432\u044b\u0445\u043e\u0434\u0430 \u0438\u0437 \u0446\u0438\u043a\u043b\u0430     var loopBody = il.DefineLabel();          \/\/ \u041e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043a\u0443 \u043d\u0430 \u0442\u0435\u043b\u043e \u0446\u0438\u043a\u043b\u0430      il.LoadZero();            \/\/      il.SetLocal(index);       \/\/ \u041e\u0431\u043d\u0443\u043b\u044f\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441     il.Jump(loopCondition);   \/\/ \u041f\u0440\u044b\u0433\u0430\u0435\u043c \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0446\u0438\u043a\u043b\u0430      il.MarkLabel(loopBody);   \/\/ \u041e\u0442\u043c\u0435\u0447\u0430\u0435\u043c \u043d\u0430\u0447\u0430\u043b\u043e \u0442\u0435\u043b\u0430 \u0446\u0438\u043a\u043b\u0430     {         var xElement = il.GetArrayElement(elementType, x, index); \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430         var yElement = il.GetArrayElement(elementType, y, index); \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430         CompareObjectsInternal(elementType, xElement, yElement);  \/\/ \u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b         il.Increment(index);                                      \/\/ \u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u0441\u0447\u0451\u0442\u0447\u0438\u043a     }      il.MarkLabel(loopCondition);     \/\/ \u041e\u0442\u043c\u0435\u0447\u0430\u0435\u043c \u043c\u0435\u0442\u043a\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0432\u044b\u0445\u043e\u0434\u0430 \u0438\u0437 \u0446\u0438\u043a\u043b\u0430     {         il.LoadLocal(index);         \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435  \u0438\u043d\u0434\u0435\u043a\u0441\u0430         il.LoadArrayLength(x);       \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0434\u043b\u0438\u043d\u0443 \u043c\u0430\u0441\u0441\u0438\u0432\u0430         il.JumpWhenLess(loopBody);   \/\/ \u0415\u0441\u043b\u0438 \u0438\u043d\u0434\u0435\u043a\u0441 \u043d\u0435 \u0432\u044b\u0448\u0435\u043b \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430, \u0442\u043e \u043f\u0440\u044b\u0433\u0430\u0435\u043c \u0432 \u0442\u0435\u043b\u043e \u0446\u0438\u043a\u043b\u0430     } } <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u043c\u044b \u0443\u0436\u0435 \u043e\u0442\u043c\u0435\u0447\u0430\u043b\u0438 \u0432\u044b\u0448\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 <s>\u0442\u0440\u0430\u0432\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0441\u0438\u0445\u0438\u043a\u0443<\/s> \u0437\u0430\u0441\u043e\u0440\u044f\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043a\u043e\u0434\u0430\u043c\u0438 \u043a\u043e\u043c\u0430\u043d\u0434, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435 \u043a\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435 \u0442\u0430\u043a \u0443\u0436 \u0438 \u0441\u0442\u0440\u0430\u0448\u043d\u043e. \u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 <code>CompareArrays<\/code> \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0434\u043b\u0438\u043d\u044b \u043c\u0430\u0441\u0441\u0438\u0432 \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442 \u043a \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c\u0443 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0440\u0430\u0432\u043d\u044b. \u0414\u0430\u043b\u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0446\u0438\u043a\u043b \u043f\u043e\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432, \u043d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u0432 IL \u043d\u0435\u0442 \u0442\u0430\u043a\u0438\u0445 \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u043a\u0430\u043a \u0446\u0438\u043a\u043b\u044b, \u0442\u043e \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432: \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0447\u0451\u0442\u0447\u0438\u043a\u0430, \u0442\u0435\u043b\u043e \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0432\u044b\u0445\u043e\u0434\u0430 \u0438\u0437 \u0446\u0438\u043a\u043b\u0430. \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0436\u0435 \u043c\u0435\u0436\u0434\u0443 \u044d\u0442\u0438\u043c\u0438 \u0431\u043b\u043e\u043a\u0430\u043c\u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 (<code>Jump, JumpWhenLess<\/code>) \u043d\u0430 \u043c\u0435\u0442\u043a\u0438 <code>loopBody, loopCondition<\/code>.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u0434 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>\/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0432 \u0441\u0442\u0435\u043a \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 public static void LoadLocal(this ILGenerator il, LocalBuilder x) =&gt; il.Emit(OpCodes.Ldloc, x);  \/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 public static void SetLocal(this ILGenerator il, LocalBuilder x) =&gt; il.Emit(OpCodes.Stloc, x);  \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0432 \u0441\u0442\u0435\u043a \u0434\u043b\u0438\u043d\u0443 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430 public static void LoadArrayLength(this ILGenerator il, LocalBuilder array) {     il.LoadLocal(array);     il.Emit(OpCodes.Ldlen);     il.Emit(OpCodes.Conv_I4); }  \/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u043c\u0430\u0441\u0441\u0438\u0432 \u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u0430, \u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0432 \u0441\u0442\u0435\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u043c public static void LoadArrayElement(this ILGenerator il) =&gt; il.Emit(OpCodes.Ldelem_I4);  \/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u0432\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0443\u044e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u043c public static LocalBuilder GetArrayElement(this ILGenerator il, Type elementType, LocalBuilder array, LocalBuilder index) {     var x = il.DeclareLocal(elementType);     il.LoadLocal(array);     il.LoadLocal(index);     il.LoadArrayElement();     il.SetLocal(x);     return x; }  \/\/ \u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443 public static void Increment(this ILGenerator il, LocalBuilder x) {     il.LoadLocal(x);     il.LoadOne();     il.Emit(OpCodes.Add);     il.SetLocal(x); } <\/code><\/pre>\n<\/div>\n<\/div>\n<p>  \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c <code>DynamicCodeComparer<\/code> \u043a \u0442\u0438\u043f\u0443 <code>SimpleClass<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440\u0430:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 &#8212; IL<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>.method public static  \tbool __DynamicCompare ( \t\tobject '', \t\tobject '' \t) cil managed  { \t\/\/ Method begins at RVA 0x2050 \t\/\/ Code size 215 (0xd7) \t.maxstack 15 \t.locals init ( \t\t[0] class SimpleClass, \t\t[1] class SimpleClass, \t\t[2] int32, \t\t[3] int32, \t\t[4] valuetype Struct, \t\t[5] valuetype Struct, \t\t[6] int32, \t\t[7] int32, \t\t[8] float64, \t\t[9] float64, \t\t[10] string, \t\t[11] string \t)  \tIL_0000: ldarg.0 \tIL_0001: castclass SimpleClass \tIL_0006: stloc.0 \tIL_0007: ldarg.1 \tIL_0008: castclass SimpleClass \tIL_000d: stloc.1 \tIL_000e: ldloc.0 \tIL_000f: ldloc.1 \tIL_0010: beq IL_00d5  \tIL_0015: ldloc.0 \tIL_0016: ldnull \tIL_0017: ceq \tIL_0019: ldloc.1 \tIL_001a: ldnull \tIL_001b: ceq \tIL_001d: beq IL_0024  \tIL_0022: ldc.i4.0 \tIL_0023: ret  \tIL_0024: ldloc.0 \tIL_0025: callvirt instance int32 SimpleClass::get_A() \tIL_002a: stloc.2 \tIL_002b: ldloc.1 \tIL_002c: callvirt instance int32 SimpleClass::get_A() \tIL_0031: stloc.3 \tIL_0032: ldloc.2 \tIL_0033: ldloc.3 \tIL_0034: beq IL_003b  \tIL_0039: ldc.i4.0 \tIL_003a: ret  \tIL_003b: ldloc.0 \tIL_003c: callvirt instance valuetype Struct SimpleClass::get_B() \tIL_0041: stloc.s 4 \tIL_0043: ldloc.1 \tIL_0044: callvirt instance valuetype Struct SimpleClass::get_B() \tIL_0049: stloc.s 5 \tIL_004b: ldloca.s 4 \tIL_004d: call instance int32 Struct::get_A() \tIL_0052: stloc.s 6 \tIL_0054: ldloca.s 5 \tIL_0056: call instance int32 Struct::get_A() \tIL_005b: stloc.s 7 \tIL_005d: ldloc.s 6 \tIL_005f: ldloc.s 7 \tIL_0061: beq IL_0068  \tIL_0066: ldc.i4.0 \tIL_0067: ret  \tIL_0068: ldloca.s 4 \tIL_006a: call instance float64 Struct::get_B() \tIL_006f: stloc.s 8 \tIL_0071: ldloca.s 5 \tIL_0073: call instance float64 Struct::get_B() \tIL_0078: stloc.s 9 \tIL_007a: ldloc.s 8 \tIL_007c: call bool [mscorlib]System.Double::IsNaN(float64) \tIL_0081: ldloc.s 9 \tIL_0083: call bool [mscorlib]System.Double::IsNaN(float64) \tIL_0088: and \tIL_0089: brtrue IL_0099  \tIL_008e: ldloc.s 8 \tIL_0090: ldloc.s 9 \tIL_0092: beq IL_0099  \tIL_0097: ldc.i4.0 \tIL_0098: ret  \tIL_0099: ldloca.s 4 \tIL_009b: call instance string Struct::get_C() \tIL_00a0: stloc.s 10 \tIL_00a2: ldloca.s 5 \tIL_00a4: call instance string Struct::get_C() \tIL_00a9: stloc.s 11 \tIL_00ab: ldloc.s 10 \tIL_00ad: ldloc.s 11 \tIL_00af: beq IL_00d5  \tIL_00b4: ldloc.s 10 \tIL_00b6: ldnull \tIL_00b7: ceq \tIL_00b9: ldloc.s 11 \tIL_00bb: ldnull \tIL_00bc: ceq \tIL_00be: beq IL_00c5  \tIL_00c3: ldc.i4.0 \tIL_00c4: ret  \tIL_00c5: ldloc.s 10 \tIL_00c7: ldloc.s 11 \tIL_00c9: call instance bool [mscorlib]System.String::Equals(string) \tIL_00ce: brtrue IL_00d5  \tIL_00d3: ldc.i4.0 \tIL_00d4: ret  \tIL_00d5: ldc.i4.1 \tIL_00d6: ret } \/\/ end of method Test::__DynamicCompare <\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 &#8212; C# (\u0434\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ILSpy)<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>public static bool __DynamicCompare(object obj, object obj2) { \tSimpleClass simpleClass = (SimpleClass)obj; \tSimpleClass simpleClass2 = (SimpleClass)obj2; \tif (simpleClass != simpleClass2) \t{ \t\tif (simpleClass == null != (simpleClass2 == null)) \t\t{ \t\t\treturn false; \t\t} \t\tint a = simpleClass.A; \t\tint a2 = simpleClass2.A; \t\tif (a != a2) \t\t{ \t\t\treturn false; \t\t} \t\tStruct b = simpleClass.B; \t\tStruct b2 = simpleClass2.B; \t\tint a3 = b.get_A(); \t\tint a4 = b2.get_A(); \t\tif (a3 != a4) \t\t{ \t\t\treturn false; \t\t} \t\tdouble b3 = b.get_B(); \t\tdouble b4 = b2.get_B(); \t\tif (!(double.IsNaN(b3) & double.IsNaN(b4)) && b3 != b4) \t\t{ \t\t\treturn false; \t\t} \t\tstring c = b.get_C(); \t\tstring c2 = b2.get_C(); \t\tif (c != c2) \t\t{ \t\t\tif (c == null != (c2 == null)) \t\t\t{ \t\t\t\treturn false; \t\t\t} \t\t\tif (!c.Equals(c2)) \t\t\t{ \t\t\t\treturn false; \t\t\t} \t\t} \t} \treturn true; } <\/code><\/pre>\n<\/div>\n<\/div>\n<p>  \u0414\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u043d \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043a \u0447\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u043f\u0440\u0438\u0434\u0440\u0430\u0442\u044c\u0441\u044f, \u0442\u0430\u043a \u044d\u0442\u043e \u043e\u0431\u0438\u043b\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u043d\u043e \u044d\u0442\u043e, \u043a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f, \u0438\u0437\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0441\u0442\u0432\u0430.<\/p>\n<h5>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b<\/h5>\n<p>  \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 <code>DynamicCodeComparer, ReflectionComparer<\/code> \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043d\u0430 \u0442\u0435\u0445 \u0436\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043b\u0438 \u043d\u0430\u0448 \u043c\u0438\u043a\u0440\u043e\u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u0434\u043b\u044f \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u0430\u0440\u0435\u0440\u0430. \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f IL \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0435\u0439.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u0434 \u043c\u0438\u043a\u0440\u043e\u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code>public struct Struct {     private int m_a;     private double m_b;     private string m_c;      public int A =&gt; m_a;     public double B =&gt; m_b;     public string C =&gt; m_c;      public Struct(int a, double b, string c)     {         m_a = a;         m_b = b;         m_c = c;     } }  public class SimpleClass {     public int A { get; set; }     public Struct B { get; set; } }  public class ComplexClass {     public int A { get; set; }     public IntPtr B { get; set; }     public UIntPtr C { get; set; }     public string D { get; set; }     public SimpleClass E { get; set; }     public int? F { get; set; }     public int[] G { get; set; }     public List&lt;int&gt; H { get; set; }     public double I { get; set; }     public float J { get; set; } }  [BenchmarkTask(platform: BenchmarkPlatform.X86, jitVersion: BenchmarkJitVersion.LegacyJit)] [BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.LegacyJit)] [BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.RyuJit)] public class ComplexComparisonTest {     private static int[] MakeArray(int count)     {         var array = new int[count];          for (int i = 0; i &lt; array.Length; ++i)             array[i] = i;          return array;     }      private static List&lt;int&gt; MakeList(int count)     {         var list = new List&lt;int&gt;(count);          for (int i = 0; i &lt; list.Count; ++i)             list.Add(i);          return list;     }      private ComplexClass x = new ComplexClass     {         A = 2,         B = new IntPtr(2),         C = new UIntPtr(2),         D = &quot;Habrahabr!&quot;,         E = new SimpleClass { A = 42, B = new Struct(42, 3.14, &quot;meow&quot;) },         F = 1,         G = MakeArray(100),         H = MakeList(100),         I = double.MaxValue,         J = float.MaxValue     };      private ComplexClass y = new ComplexClass     {         A = 2,         B = new IntPtr(2),         C = new UIntPtr(2),         D = &quot;Habrahabr!&quot;,         E = new SimpleClass { A = 42, B = new Struct(42, 3.14, &quot;meow&quot;) },         F = 1,         G = MakeArray(100),         H = MakeList(100),         I = double.MaxValue,         J = float.MaxValue     };      private ReflectionComparer reflectionComparer = new ReflectionComparer();     private DynamicCodeComparer dynamicCodeComparer = new DynamicCodeComparer();      [Benchmark]     public void ReflectionCompare()     {         var _ = reflectionComparer.Equals(x, y);     }      [Benchmark]     public void DynamicCodeCompare()     {         var _ = dynamicCodeComparer.Equals(x, y);     }      [Benchmark]     public void ManualCompare()     {         var _ = CompareComplexObjects();     }      private bool CompareComplexObjects()     {         if (x == y) return true;         if (x.A != y.A) return false;         if (x.B != y.B) return false;         if (x.C != y.C) return false;         if (x.D != y.D) return false;         if (x.E != y.E)         {             if (x.E.A != y.E.A) return false;             var s1 = x.E.B;             var s2 = y.E.B;             if (s1.A != s2.A) return false;             if (!s1.B.Equals(s2.B)) return false;             if (s1.C != s2.C) return false;         }         if (x.F != y.F) return false;         if (x.G != y.G)         {             if (x.G?.Length != y.G?.Length) return false;             int[] a = x.G, b = y.G;             for (int i = 0; i &lt; a.Length; ++i)             {                 if (a[i] != b[i]) return false;             }         }         if (x.H != y.H)         {             if (!x.H.SequenceEqual(y.H)) return false;         }         if (!x.I.Equals(y.I)) return false;         if (!x.J.Equals(y.J)) return false;         return true;     } }  [BenchmarkTask(platform: BenchmarkPlatform.X86, jitVersion: BenchmarkJitVersion.LegacyJit)] [BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.LegacyJit)] [BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.RyuJit)] public class SimpleComparisonTest {     private SimpleClass x = new SimpleClass { A = 42, B = new Struct(42, 3.14, &quot;meow&quot;) };     private SimpleClass y = new SimpleClass { A = 42, B = new Struct(42, 3.14, &quot;meow&quot;) };      private ReflectionComparer reflectionComparer = new ReflectionComparer();     private DynamicCodeComparer dynamicCodeComparer = new DynamicCodeComparer();      [Benchmark]     public void ReflectionCompare()     {         var _ = reflectionComparer.Equals(x, y);     }      [Benchmark]     public void DynamicCodeCompare()     {         var _ = dynamicCodeComparer.Equals(x, y);     }      [Benchmark]     public void ManualCompare()     {         var _ = CompareSimpleObjects();     }      private bool CompareSimpleObjects()     {         if (x == y) return true;         if (x.A != y.A) return false;         var s1 = x.B;         var s2 = y.B;         if (s1.A != s2.A) return false;         if (!s1.B.Equals(s2.B)) return false;         if (s1.C != s2.C) return false;         return true;     } } <\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <b>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 ComplexClass<\/b>  <\/p>\n<table>\n<tr>\n<th>Method<\/th>\n<th>Platform<\/th>\n<th>Jit<\/th>\n<th>AvrTime<\/th>\n<th>StdDev<\/th>\n<th>op\/s<\/th>\n<\/tr>\n<tr>\n<td>DynamicCodeComparer<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>1,104.7155 ns<\/td>\n<td>32.9474 ns<\/td>\n<td>905,210.51<\/td>\n<\/tr>\n<tr>\n<td>Handwritten<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>1,360.3273 ns<\/td>\n<td>39.9703 ns<\/td>\n<td>735,117.32<\/td>\n<\/tr>\n<tr>\n<td>ReflectionComparer<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>38,043.3600 ns<\/td>\n<td>2,261.3159 ns<\/td>\n<td>26,290.11<\/td>\n<\/tr>\n<tr>\n<td>DynamicCodeComparer<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>834.8742 ns<\/td>\n<td>58.1986 ns<\/td>\n<td>1,197,785.93<\/td>\n<\/tr>\n<tr>\n<td>Handwritten<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>968.3789 ns<\/td>\n<td>33.1622 ns<\/td>\n<td>1,032,653.82<\/td>\n<\/tr>\n<tr>\n<td>ReflectionComparer<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>37,751.3104 ns<\/td>\n<td>1,763.3172 ns<\/td>\n<td>26,489.20<\/td>\n<\/tr>\n<tr>\n<td>DynamicCodeComparer<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>776.0265 ns<\/td>\n<td>22.8038 ns<\/td>\n<td>1,288,615.79<\/td>\n<\/tr>\n<tr>\n<td>Handwritten<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>915.5713 ns<\/td>\n<td>26.0536 ns<\/td>\n<td>1,092,214.32<\/td>\n<\/tr>\n<tr>\n<td>ReflectionComparer<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>32,382.2746 ns<\/td>\n<td>1,748.4016 ns<\/td>\n<td>30,881.10<\/td>\n<\/tr>\n<\/table>\n<p>  <b>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 SimpleClass<\/b>  <\/p>\n<table>\n<tr>\n<th>Method<\/th>\n<th>Platform<\/th>\n<th>Jit<\/th>\n<th>AvrTime<\/th>\n<th>StdDev<\/th>\n<th>op\/s<\/th>\n<\/tr>\n<tr>\n<td>DynamicCodeComparer<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>215.7626 ns<\/td>\n<td>8.2063 ns<\/td>\n<td>4,634,725.08<\/td>\n<\/tr>\n<tr>\n<td>Handwritten<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>160.4945 ns<\/td>\n<td>6.8949 ns<\/td>\n<td>6,230,741.94<\/td>\n<\/tr>\n<tr>\n<td>ReflectionComparer<\/td>\n<td>X64<\/td>\n<td>LegacyJit<\/td>\n<td>6,654.3290 ns<\/td>\n<td>380.7790 ns<\/td>\n<td>150,278.15<\/td>\n<\/tr>\n<tr>\n<td>DynamicCodeComparer<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>168.4194 ns<\/td>\n<td>9.4654 ns<\/td>\n<td>5,937,569.56<\/td>\n<\/tr>\n<tr>\n<td>Handwritten<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>87.8513 ns<\/td>\n<td>3.3118 ns<\/td>\n<td>11,382,874.20<\/td>\n<\/tr>\n<tr>\n<td>ReflectionComparer<\/td>\n<td>X64<\/td>\n<td>RyuJit<\/td>\n<td>6,954.6437 ns<\/td>\n<td>387.1803 ns<\/td>\n<td>143,789.85<\/td>\n<\/tr>\n<tr>\n<td>DynamicCodeComparer<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>180.4105 ns<\/td>\n<td>6.5036 ns<\/td>\n<td>5,542,914.59<\/td>\n<\/tr>\n<tr>\n<td>Handwritten<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>93.0846 ns<\/td>\n<td>4.0584 ns<\/td>\n<td>10,742,923.17<\/td>\n<\/tr>\n<tr>\n<td>ReflectionComparer<\/td>\n<td>X86<\/td>\n<td>LegacyJit<\/td>\n<td>6,431.5783 ns<\/td>\n<td>314.5633 ns<\/td>\n<td>155,483.09<\/td>\n<\/tr>\n<\/table>\n<p>  <\/p>\n<h5>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h5>\n<p>  \u0424\u0440\u0435\u0434 \u0411\u0440\u0443\u043a\u0441 \u0432 \u0441\u0432\u043e\u0435\u0439 \u0437\u043d\u0430\u043c\u0435\u043d\u0438\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u00abNo silver bullet\u00bb \u043f\u043e\u0434\u0447\u0451\u0440\u043a\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 (accidental complexity) \u0438 \u0438\u043c\u043c\u0430\u043d\u0435\u043d\u0442\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 (essential complexity), \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435 \u043f\u0440\u0438\u0441\u0443\u0449\u0438\u043c\u0438 \u0441\u0430\u043c\u043e\u0439 \u0440\u0435\u0448\u0430\u0435\u043c\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0438 \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0442\u0430\u043a\u043e\u0439 \u043d\u0435\u043d\u0443\u0436\u043d\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0432\u043e\u0437\u043d\u0438\u043a\u0448\u0435\u0439 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u0434\u0438\u0437\u0430\u0439\u043d\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043d\u0435 \u0431\u044b\u043b\u043e \u0443\u0434\u0435\u043b\u0435\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043a\u0438\u0434\u0430\u0442\u044c\u0441\u044f \u0441\u043a\u043e\u0440\u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0444\u0435\u043a\u0441\u0438\u044e \u0438\u043b\u0438 \u043a\u043e\u0434\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0435\u0449\u0451 \u043d\u0435 \u043f\u043e\u0437\u0434\u043d\u043e \u043f\u043e\u0434\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0432 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043c\u043e\u0433\u043b\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u0447\u043a\u043e\u0439, \u0435\u0441\u043b\u0438 \u0431\u044b \u0432\u0441\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u043b\u0438 \u0431\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>IEquatable&lt;T&gt;<\/code>. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u0443-\u043d\u0438\u0431\u0443\u0434\u044c \u0435\u0449\u0451 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c.<\/p>\n<p>  \u0417\u0430\u0441\u0438\u043c \u043e\u0442\u043a\u043b\u0430\u043d\u0438\u0432\u0430\u044e\u0441\u044c, \u0434\u043e\u0440\u043e\u0433\u0438\u0435 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0438. \u041f\u0440\u0438\u044f\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f! <\/p>\n<p>  \u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b:  <\/p>\n<ul>\n<li> <a href=\"https:\/\/github.com\/akarpov89\/DynamicComparer\">\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a \u0441\u0442\u0430\u0442\u044c\u0435<\/a>   <\/li>\n<li> <a href=\"http:\/\/www.williamspublishing.com\/Books\/978-5-8459-1819-2.html\">\u0414\u0436\u043e\u0437\u0435\u0444 \u0410\u043b\u0431\u0430\u0445\u0430\u0440\u0438, \u0411\u0435\u043d \u0410\u043b\u0431\u0430\u0445\u0430\u0440\u0438. C# 5.0. \u0421\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a. \u041f\u043e\u043b\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044f\u0437\u044b\u043a\u0430<\/a>    <\/li>\n<li> <a href=\"http:\/\/www.apress.com\/9781590596463\">Serge Lidin. Expert .NET 2.0 IL Assembler<\/a>   <\/li>\n<li> MSDN \u2014 <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit%28v%3Dvs.110%29.aspx\">System.Reflection.Emit Namespace<\/a>   <\/li>\n<li> \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/github.com\/PerfDotNet\/BenchmarkDotNet\">BenchmarkDotNet<\/a>   <\/li>\n<li> <a href=\"http:\/\/tryroslyn.azurewebsites.net\/\">Try Roslyn<\/a>   <\/li>\n<\/ul>\n<div class=\"clear\"><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/269699\/\"> http:\/\/habrahabr.ru\/post\/269699\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>       <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/028\/1fa\/7c0\/0281fa7c0f364af7bd6fce4cc3b751de.jpg\" align=\"left\"\/> <\/p>\n<p>  \u041d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u043e \u043c\u043d\u043e\u0439 \u0432\u0441\u0442\u0430\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u041d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u044e\u0430\u043d\u0441: \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u2014 \u0441\u0430\u043c\u044b\u0435 \u0447\u0442\u043e \u043d\u0438 \u043d\u0430 \u0435\u0441\u0442\u044c <code>object<\/code>&#8216;\u044b, \u0430 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u043e \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u043d\u0430\u0431\u043e\u0440\u0443 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432. \u041f\u0440\u0438\u0447\u0451\u043c \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e \u0442\u0438\u043f\u044b \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms131187(v=vs.110).aspx\"><code>IEquatable&lt;T&gt;<\/code><\/a>. <\/p>\n<p>  \u0411\u044b\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044e. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u043e\u043d\u043a\u043e\u0441\u0442\u0435\u0439 \u0438 \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0441\u0447\u0451\u0442\u0435 \u043f\u0440\u0438\u0431\u0435\u0433\u043d\u0443\u043b \u043a <s>\u0447\u0451\u0440\u043d\u043e\u0439 \u043c\u0430\u0433\u0438\u0438<\/s> \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 IL. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043e\u043f\u044b\u0442\u043e\u043c \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044f \u0440\u0435\u0448\u0430\u043b \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443. \u0415\u0441\u043b\u0438 \u0412\u0430\u0441 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u0430 \u0442\u0435\u043c\u0430, \u0442\u043e \u043f\u0440\u043e\u0448\u0443 \u043f\u043e\u0434 \u043a\u0430\u0442!  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-266986","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/266986","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=266986"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/266986\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=266986"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=266986"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=266986"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}