And*_*tan 5 .net c# architecture
我用一大堆有问题的背景开始这个问题; 架构背后的接口和基本原理.
然后我意识到 - "这就是这样 - 保持简单并达到目的".
所以这里.
我有一个这样的课:
public class AGenericType<T> : AGenericTypeBase
{
T Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
当然,.Net允许我这样做:
AGenericType<AGenericType<int>> v;
Run Code Online (Sandbox Code Playgroud)
但是,在使用环境中AGenericType<T>,以同样的方式执行此操作是无稽之谈,因为这样做是无意义的:
Nullable<Nullable<double>> v;
Run Code Online (Sandbox Code Playgroud)
我希望能够做的是限制这种泛型类型,这样就不可能创建这样的实例,甚至在T派生它时也会声明对类型的引用AGenericTypeBase- 最好是在编译时.
现在一个有趣的事情是Nullable<T>我在这里给出的例子确实会产生编译器错误.但我无法看到如何Nullable<T>限制T非Nullable<T>类型 - 因为Nullable<T>是一个结构,并且我能找到的唯一通用约束(即使在IL中,它通常会产生编译器机密,就像那些带有委托的那些)where T:struct.所以我认为一个人必须是编译器黑客(编辑:请参阅下面的@Daniel Hilgarth的回答+评论,以便对此进行一些探索).编译器黑客当然不能重复!
至于我自己的方案中,IL和C#不容许负断言约束是这样的:
public class AGenericType<T> : where !T:AGenericTypeBase
Run Code Online (Sandbox Code Playgroud)
(注意约束中的'!')
但我可以使用哪种替代方案?
我想到了两个:
1)在构造函数中生成的运行时异常AGenericType<T>:
public AGenericType(){
if(typeof(AGenericBase).IsAssignableFrom(typeof(T)))
throw new InvalidOperationException();
}
Run Code Online (Sandbox Code Playgroud)
但这并不能真正反映错误的本质 - 因为问题是泛型参数,因此是整个类型; 不只是那个例子.
2)相反,相同的运行时异常,但在静态初始化器中生成AGenericType<T>:
static AGenericType(){
if(typeof(AGenericBase).IsAssignableFrom(typeof(T)))
throw new InvalidOperationException();
}
Run Code Online (Sandbox Code Playgroud)
但后来我面临的问题是这个异常会被包含在内部TypeInitializationException并且可能会引起混淆(根据我的经验,实际上读取整个异常层次结构的开发人员实际上很薄).
对我而言,这是IL和C#中"否定断言"泛型约束的明显例子 - 但由于这不太可能发生,你会怎么做?
最后,我在泛型类型的静态初始化程序中遇到了异常,因为它更清楚地表明调用者对该类型的使用存在问题,而不是传递给构造函数的运行时参数。该错误很容易被调用者修复,所以我认为这是最好的妥协。
| 归档时间: |
|
| 查看次数: |
199 次 |
| 最近记录: |