- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有两个复杂的对象,例如 Object1
和 Object2
。 它们有大约 5 个级别的子对象。
我需要最快的方法来判断它们是否相同。
这在 C# 4.0 中如何完成?
最佳答案
实现 IEquatable<T>
(通常与覆盖继承的 Object.Equals
和 Object.GetHashCode
方法结合使用)所有自定义类型。在复合类型的情况下,调用包含的类型'Equals
包含类型中的方法。对于包含的集合,使用 SequenceEqual
扩展方法,内部调用 IEquatable<T>.Equals
或 Object.Equals
在每个元素上。这种方法显然需要您扩展类型的定义,但其结果比任何涉及序列化的通用解决方案都要快。
编辑:这是一个具有三层嵌套的人为示例。
对于值类型,您通常可以调用它们的 Equals
方法。即使从未显式分配字段或属性,它们仍将具有默认值。
对于引用类型,你应该先调用 ReferenceEquals
,它检查引用相等性——当您碰巧引用同一个对象时,这将提高效率。它还会处理两个引用都为空的情况。如果该检查失败,请确认您的实例的字段或属性不为空(以避免 NullReferenceException
)并调用其 Equals
方法。由于我们的成员类型正确,IEquatable<T>.Equals
方法被直接调用,绕过重写的 Object.Equals
方法(由于类型转换,其执行速度会稍微慢一些)。
当您覆盖 Object.Equals
时,您还需要覆盖 Object.GetHashCode
;为了简洁起见,我在下面没有这样做。
public class Person : IEquatable<Person>
{
public int Age { get; set; }
public string FirstName { get; set; }
public Address Address { get; set; }
public override bool Equals(object obj)
{
return this.Equals(obj as Person);
}
public bool Equals(Person other)
{
if (other == null)
return false;
return this.Age.Equals(other.Age) &&
(
object.ReferenceEquals(this.FirstName, other.FirstName) ||
this.FirstName != null &&
this.FirstName.Equals(other.FirstName)
) &&
(
object.ReferenceEquals(this.Address, other.Address) ||
this.Address != null &&
this.Address.Equals(other.Address)
);
}
}
public class Address : IEquatable<Address>
{
public int HouseNo { get; set; }
public string Street { get; set; }
public City City { get; set; }
public override bool Equals(object obj)
{
return this.Equals(obj as Address);
}
public bool Equals(Address other)
{
if (other == null)
return false;
return this.HouseNo.Equals(other.HouseNo) &&
(
object.ReferenceEquals(this.Street, other.Street) ||
this.Street != null &&
this.Street.Equals(other.Street)
) &&
(
object.ReferenceEquals(this.City, other.City) ||
this.City != null &&
this.City.Equals(other.City)
);
}
}
public class City : IEquatable<City>
{
public string Name { get; set; }
public override bool Equals(object obj)
{
return this.Equals(obj as City);
}
public bool Equals(City other)
{
if (other == null)
return false;
return
object.ReferenceEquals(this.Name, other.Name) ||
this.Name != null &&
this.Name.Equals(other.Name);
}
}
更新:这个答案是几年前写的。从那时起,我开始放弃实现 IEquality<T>
对于此类场景的可变类型。平等有两个概念:同一性 和等价。在内存表示级别,这些通常被区分为“引用相等”和“值相等”(参见 Equality Comparisons )。然而,同样的区别也适用于域级别。假设您的 Person
类有一个 PersonId
属性(property),每个不同的现实世界的人都是独一无二的。两个对象是否应该具有相同的 PersonId
但不同Age
值被认为是相等的还是不同的?上面的答案假设一个是在等价之后。但是,IEquality<T>
有很多用法。接口(interface),例如集合,假设此类实现提供身份。例如,如果您要填充 HashSet<T>
, 你通常会期望一个 TryGetValue(T,T)
调用以返回仅共享参数标识的现有元素,不一定是内容完全相同的等效元素。 GetHashCode
上的注释强制执行此概念:
In general, for mutable reference types, you should override
GetHashCode()
only if:
- You can compute the hash code from fields that are not mutable; or
- You can ensure that the hash code of a mutable object does not change while the object is contained in a collection that relies on its hash code.
关于c# - 比较两个复杂对象的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10454519/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!