提问人:myavuzselim 提问时间:12/16/2022 最后编辑:myavuzselim 更新时间:12/17/2022 访问量:146
为结构实现 IEquatable,并通过引用传递
Implement IEquatable for struct, and pass by reference
问:
是否可以从结构实现 IEquatable,但通过引用传递 compare 参数?
例:
struct BigToCopy : IEquatable<BigToCopy>
{
int x, y, z, w, foo bar, etc;
bool Equals(in BigToCopy other) // does not compile with 'in' parameter
{
}
}
它不会编译,因为当有“in”关键字时,它似乎不会实现。IEquatable<BigToCopy>
这个是可以的,但它按值复制:
struct BigToCopy : IEquatable<BigToCopy>
{
int x, y, z, w, foo bar, etc;
bool Equals(BigToCopy other) // does compile
{
}
}
IEqualityComparer
据我所知,也有同样的问题。它要求参数按值传递。
编译器优化会避免复制吗,即使我们按值传递?注意:我在 Unity 上。使用 mono 和 il2cpp。
编辑:好的,让我们更具体一点。我们的代码库中有许多类是这样实现的:
struct Vertex
{
public Point3d Position; // 3 doubles
public Vector3d Normal; // 3 doubles
public Vector2d UV; // 2 doubles
public Color Color; // 4 bytes
// possibly some other vertex data
public override bool Equals(object obj) { ... }
public bool Equals(in Vertex vertex) { ... }
}
有多个这样的类。它们以 HashSet、Dictionaries 等形式被放入集合中。在某些情况下,它们还通过明确的调用来进行比较。这些对象可以创建数千甚至数百万个,并以某种方式进行处理。它们通常位于热代码路径中。Equals
最近,我发现使用这些对象进行字典查找会导致对象分配。原因是:这些对象不实现 IEquatable。因此,字典会改为调用重载,这会导致装箱(= 内存分配)。Equals(object obj)
我现在正在通过实现 IEquatable 接口并删除“in”关键字来修复这些类。但是有一些现有的代码直接调用这些 Equals 方法,我不确定我是否严重影响了性能。我可以尝试,但是我以这种方式修复了很多类,所以检查的工作量太大了。 相反,我添加了另一种方法:
public bool EqualsPassByRef(in Vertex vertex) { ... }
并替换 by 的显式调用。Equals
EqualsPassByRef
这种方式工作正常。与以前相比,性能会更好。我只是想知道:也许有一种方法可以让 C# 从字典中调用“in”版本。这样就不需要“EqualsPassByRef”版本了,使代码看起来更好(在字典查找中也可能更快)。从答案中,我得出结论,这是不可能的。好吧,这还是可以的。
顺便说一句:我是 C# 的新手。我来自一个 C++ 世界。
答: 暂无答案
评论
BigToCopy
ref struct
BigToCopy
class
Equals
Equals
public bool /* IEquatable*/ Equals(BigToCopy other) { ... } public bool /* other */ Equals(ref BigToCopy other) { ... }
IEquatable