gpt4 book ai didi

c# - 防止将特定的类型层次结构用于泛型参数

转载 作者:太空狗 更新时间:2023-10-29 23:26:16 26 4
gpt4 key购买 nike

我以大量相关类型的背景开始这个问题;架构背后的界面和基本原理。

然后我意识到 - “这就是 SO - 保持简单,切入正题”。

就这样吧。

我有这样一个类:

public class AGenericType<T> : AGenericTypeBase
{
T Value { get; set; }
}

当然,.Net 允许我这样做:

AGenericType<AGenericType<int>> v;

但是,在 AGenericType<T> 的上下文中的用法,这样做是无意义的,就像这样做是无意义的一样:

Nullable<Nullable<double>> v;

我想做的是限制这个通用类型,这样当它是 T 时就不可能创建这样的实例甚至声明对该类型的引用。源自 AGenericTypeBase - 最好在编译时。

现在有趣的是 Nullable<T>我在此处给出的示例确实 生成了编译器错误。但我看不出如何 Nullable<T>限制 T到非 Nullable<T>类型 - 自 Nullable<T>是一个结构,我能找到的唯一通用约束(即使在 IL 中,它经常产生编译器 secret ,就像那些有委托(delegate)的)是 where T:struct .所以我认为这一定是一个编译器 hack(编辑:请参阅@Daniel Hilgarth 的回答 + 下面的评论以对此进行一些探索)。我当然不能重复的编译器技巧!

对于我自己的场景,IL 和 C# 不允许像这样的否定断言约束:

public class AGenericType<T> : where !T:AGenericTypeBase

(注意约束中的“!”)

但是我可以使用什么替代方案呢?

我想到了两个:

1) AGenericType<T> 的构造函数中生成运行时异常:

public AGenericType(){
if(typeof(AGenericBase).IsAssignableFrom(typeof(T)))
throw new InvalidOperationException();
}

不过,这并没有真正反射(reflect)错误的性质——因为问题出在泛型参数上,因此是整个类型;不只是那个例子。

2) 因此,相反,相同的运行时异常,但在 AGenericType<T> 的静态初始化程序中生成:

static AGenericType(){
if(typeof(AGenericBase).IsAssignableFrom(typeof(T)))
throw new InvalidOperationException();
}

但后来我遇到了这个异常将被包裹在 TypeInitializationException 中的问题。并且可能会造成混淆(根据我的经验,真正阅读整个异常层次结构的开发人员很少见)。

对我来说,这是 IL 和 C# 中“否定断言”通用约束的明显案例 - 但由于这不太可能发生,您会怎么做?

最佳答案

关于Nullable<T> : 约束 T : struct是编译器错误的原因,因为结构变量永远不能为空,而类型为 Nullable<T> 的变量可以为空。
所以,它编译器 hack,但仅以这种方式,即 Nullable<T>被视为可空值类型而不是不可空值类型。

public struct Nullable2<T> where T: struct
{
}

// Both lines will generate the same error
Nullable2<Nullable<int>> v;
Nullable<Nullable<int>> v2;

我想说的是:
Nullable<T>不执行“‘否定断言’通用约束”。

关于c# - 防止将特定的类型层次结构用于泛型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6043056/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com