C# 11能否自动实现IEquatable<T>与IComparable<T>?相关疑问
关于C#接口默认实现与值类型运算符样板代码的问题解答
问题1:为何接口virtual默认实现仍需在结构体中手动实现?
需要分两种核心场景解释:
- 实例方法的默认实现:C#8引入的接口实例默认实现,本质上属于接口类型的成员,而非实现类型的成员。对于
Int256这类值类型来说,若不在结构体中手动实现或重写接口方法,直接通过结构体实例调用接口方法会触发装箱操作(将值类型转换为接口引用类型),既带来性能损耗,也不符合值类型的设计初衷。此外,C#编译器不会自动将接口的默认实现“注入”到值类型的实例成员中,因此必须手动实现才能让结构体直接拥有这些方法。 - 静态运算符的默认实现:
==、!=等运算符属于静态成员,即便C#11支持了静态接口方法,接口的静态默认实现也不会自动成为值类型的静态成员。C#的静态成员是类型专属的,接口的静态成员仅属于接口本身,实现类型无法自动继承这些静态成员作为自己的运算符。因此你必须在Int256中手动编写运算符代码,再在其中调用接口的静态默认逻辑,无法直接复用。
举个实际示例,假设你定义了自定义接口:
public interface IAutoEquatable<T> where T : IAutoEquatable<T> { static virtual bool operator ==(T left, T right) { return left.Equals(right); } static virtual bool operator !=(T left, T right) { return !(left == right); } bool Equals(T? other); }
当Int256 : IAutoEquatable<Int256>时,编译器不会自动把接口的==运算符转为Int256的运算符,必须手动编写包装代码:
public struct Int256 : IAutoEquatable<Int256> { public bool Equals(Int256? other) { // 自定义相等逻辑 } // 必须手动实现,否则编译器报错 public static bool operator ==(Int256 left, Int256 right) { return IAutoEquatable<Int256>.operator ==(left, right); } public static bool operator !=(Int256 left, Int256 right) { return IAutoEquatable<Int256>.operator !=(left, right); } }
问题2:未来C#版本是否会解决该问题?
目前C#已经有现成的简化方案:C#10引入的record struct可以自动实现IEquatable<T>以及==、!=运算符(基于值的逐字段比较),如果你的Int256可以基于逐字段相等判断,直接用record struct就能省去大部分样板代码。
对于自定义逻辑的场景,C#设计团队一直在收集社区需求,后续版本有可能推出更灵活的特性:
- 支持实现类型自动继承接口的静态默认成员,无需手动编写运算符的包装代码;
- 增强源生成器能力,让编译器可基于接口标记自动生成所需的运算符和接口方法实现。
另外,现在你也可以通过自定义源生成器解决问题:编写一个源生成器,当检测到结构体实现IAutoEquatable<T>或IAutoComparable<T>时,自动生成对应的运算符和接口方法实现,完全省去手动编写样板代码的工作。
内容的提问来源于stack exchange,提问作者Matthew Layton
相关产品推荐
相关产品推荐

