如何在.NET泛型约束中指定不允许的类型?

13

是否可以对泛型类指定一个约束,以禁止某些类型?我不知道是否可能,如果可能的话,我也不确定语法应该是什么样子的。例如:

public class Blah<T> where : !string {
}

我似乎找不到任何符号来表示这样的约束。


不要以为这是可能的 - 但是你为什么需要这样的东西呢? - Random Dev
当有人尝试传入不受支持的类型时,期望的行为是什么? - James Johnson
我本来想排除字符串类型,但事实证明,使用 where T : struct 对于我要做的事情是有效的,因为我的类无论如何都不适用于复杂类型。 - Leslie Hanks
出于兴趣,我正在尝试找出为什么需要这种行为的原因。 - Rob van der Veer
4个回答

12

你能得到的最接近的是运行时约束。

编辑:最初我将运行时检查放在构造函数调用中。实际上,这并不是最佳选择,因为它会在每次实例化时产生开销;我认为将检查放在静态构造函数中会更加明智,因为它将针对作为T参数用于你的Blah<T>类型的每种类型调用一次:

public class Blah<T> {
    static Blah() {
        // This code will only run ONCE per T, rather than every time
        // you call new Blah<T>() even for valid non-string type Ts
        if (typeof(T) == typeof(string)) {
            throw new NotSupportedException("The 'string' type argument is not supported.");
        }
    }
}

很明显不是理想情况,但如果你设置这个限制并且记录下string不是受支持的类型参数(例如通过XML注释),你应该能够接近编译时约束的效果。


1
通常我会将在C#中无法表达的约束条件放入类构造函数中。 - CodesInChaos
要包含可以解析为字符串的类型:如果(typeof(string).IsAssignableFrom(typeof(T))),则抛出NotSupportedException异常。 - Rasmus

4
不,您不能直接指定“否定”的类型约束。

有没有其他间接的方法,而不是像断言 typeof(T) 不是某个类型? - SirPentor
@SirPentor,虽然你可以在代码中这样做,但这不是类型约束的一部分。 - Donut

2
约束只能是正面的约束,如文档所述。
你唯一能做的就是指定可以放入泛型类型的类型,但不能指定哪些类型不能放入其中。

1

以下是允许的约束条件(更多细节

  • where T: struct
  • where T : class
  • where T : new()
  • where T : [基类名称]
  • where T : [接口名称]
  • where T : U(为 T 提供的类型参数必须是或派生自为 U 提供的参数)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接