C# with关键字在泛型结构体约束下编译失败,是Bug还是预期行为?
C#泛型struct中使用with关键字的编译错误:预期行为及原因
这是预期行为,并非Bug,具体原因如下:
with表达式的依赖逻辑with表达式的核心是基于**具体类型的可修改成员(init或set属性)**创建对象副本并修改指定属性。编译器必须在编译阶段明确知晓目标成员的可修改性,才能生成正确的副本创建代码。泛型约束的局限性
在泛型方法DoSomethingWithGenericConstrainedToStruct中,T的约束仅为struct, ICountSomething:
- 接口
ICountSomething只定义了Counter的get访问器,没有暴露它的init或set能力; - 编译器无法保证所有符合约束的
struct类型,都拥有一个可通过对象初始器修改的Counter成员(比如某些实现该接口的struct可能将Counter定义为只读字段,完全不支持修改)。
由于编译阶段无法验证T类型的Counter是否满足with表达式的修改要求,因此会抛出编译错误。
- 具体结构体可正常工作的原因
对于ActualStruct这种具体类型,编译器能直接识别到它的Counter是init属性,明确支持通过对象初始器修改,因此with表达式可以正常编译执行。
泛型场景的替代实现方案
如果需要在泛型逻辑中实现类似的修改效果,可以在接口中定义专属的修改方法,让结构体实现该方法:
public interface ICountSomething<T> where T : struct, ICountSomething<T> { int Counter { get; } T WithIncrementedCounter(); } public struct ActualStruct : ICountSomething<ActualStruct> { public string Name { get; init; } public int Counter { get; init; } public ActualStruct WithIncrementedCounter() { return this with { Counter = Counter + 1 }; } } public class Blah<T> where T : struct, ICountSomething<T> { public T DoSomethingWithGenericConstrainedToStruct(T input) { return input.WithIncrementedCounter(); } }
内容的提问来源于stack exchange,提问作者Steve Wilford
相关产品推荐
相关产品推荐

