是否可以在 C# 泛型方法中定义 "not Nullable<T>" 约束?
Is it possible to define a "not Nullable<T>" constraint in a C# generic method?
在 C# 中,Nullable<T>
类型不满足 where
struct
泛型约束(据我所知,这在技术上是一个结构)。这可用于指定泛型参数必须是不可为 null 的值类型:
T DoSomething<T>() where T : struct
{
//...
}
DoSomething<int?>(); //not ok
DoSomething<int>(); //ok
当然,Nullable<T>
也不满足引用类型where
class
约束:
T DoSomething<T>() where T : class
{
//...
}
DoSomething<int?>(); //not ok
DoSomething<Foo>(); //ok
是否可以定义约束,例如它必须是引用类型或值类型而不是可空值类型?
像这样:
void DoSomething<T>() where T : class, struct //wont compile!
{
//...
}
DoSomething<int?>(); //not ok
DoSomething<int>(); //ok
DoSomething<Foo>(); //ok
不,在声明方面是不可能的。它是 struct
或 class
。
但是,您可以在 运行 时检查 typeof(T)
以确保 T
是 Nullable<T2>
Type type = typeof(T);
if(Nullable.GetUnderlyingType(type) == null)
throw new Exception();
如评论中所述,您可以使用重载 和 参数(可以是可选的)来执行此操作。我 blogged about this 刚才,但在你的情况下你想要:
public class ClassConstraint<T> where T : class
{
}
public class SomeClass<TViewModel>
{
public void Add<TValue>(Func<TViewModel, TValue> expression,
ClassConstraint<TValue> ignored = null)
where TValue : class
{
AddImpl(expression);
}
public void Add<TValue>(Func<TViewModel, TValue> expression,
Nullable<TValue> ignored = null)
where TValue : struct
{
AddImpl(expression);
}
// No constraints
private void AddImpl<TValue>(Func<TViewModel, TValue> expression)
{
...
}
}
它很丑,但它有效:
var z = new SomeClass<string>();
z.Add(x => x.Length); // Valid (non-nullable value type)
z.Add(x => x); // Valid (reference type)
z.Add(x => new DateTime?()); // Invalid (nullable value type)
在 C# 中,Nullable<T>
类型不满足 where
struct
泛型约束(据我所知,这在技术上是一个结构)。这可用于指定泛型参数必须是不可为 null 的值类型:
T DoSomething<T>() where T : struct
{
//...
}
DoSomething<int?>(); //not ok
DoSomething<int>(); //ok
当然,Nullable<T>
也不满足引用类型where
class
约束:
T DoSomething<T>() where T : class
{
//...
}
DoSomething<int?>(); //not ok
DoSomething<Foo>(); //ok
是否可以定义约束,例如它必须是引用类型或值类型而不是可空值类型?
像这样:
void DoSomething<T>() where T : class, struct //wont compile!
{
//...
}
DoSomething<int?>(); //not ok
DoSomething<int>(); //ok
DoSomething<Foo>(); //ok
不,在声明方面是不可能的。它是 struct
或 class
。
但是,您可以在 运行 时检查 typeof(T)
以确保 T
是 Nullable<T2>
Type type = typeof(T);
if(Nullable.GetUnderlyingType(type) == null)
throw new Exception();
如评论中所述,您可以使用重载 和 参数(可以是可选的)来执行此操作。我 blogged about this 刚才,但在你的情况下你想要:
public class ClassConstraint<T> where T : class
{
}
public class SomeClass<TViewModel>
{
public void Add<TValue>(Func<TViewModel, TValue> expression,
ClassConstraint<TValue> ignored = null)
where TValue : class
{
AddImpl(expression);
}
public void Add<TValue>(Func<TViewModel, TValue> expression,
Nullable<TValue> ignored = null)
where TValue : struct
{
AddImpl(expression);
}
// No constraints
private void AddImpl<TValue>(Func<TViewModel, TValue> expression)
{
...
}
}
它很丑,但它有效:
var z = new SomeClass<string>();
z.Add(x => x.Length); // Valid (non-nullable value type)
z.Add(x => x); // Valid (reference type)
z.Add(x => new DateTime?()); // Invalid (nullable value type)