【问题标题】:Is it possible to define a "not Nullable<T>" constraint in a C# generic method?是否可以在 C# 泛型方法中定义“not Nullable<T>”约束?
【发布时间】:2015-02-11 11:12:27
【问题描述】:

在 C# 中,Nullable&lt;T&gt; 类型不满足 where struct 泛型约束(而 AFAK 这在技术上是一个结构)。这可用于指定泛型参数必须是不可为空的值类型:

T DoSomething<T>() where T : struct
{
   //... 
} 
DoSomething<int?>(); //not ok
DoSomething<int>();  //ok

当然,Nullable&lt;T&gt; 也不满足引用类型 where class 约束:

T DoSomething<T>() where T : class
{
   //...
} 
DoSomething<int?>(); //not ok
DoSomething<Foo>();  //ok

这是否可以定义一个约束,例如它必须是引用类型或值类型但不能为 Nullable 值类型?

类似这样的:

void DoSomething<T>() where T : class, struct //wont compile!
{    
   //...   
} 
DoSomething<int?>(); //not ok
DoSomething<int>();  //ok
DoSomething<Foo>();  //ok

【问题讨论】:

  • 除了Nullable&lt;T&gt; 之外的所有内容?这很难。
  • 你为什么要这样做?
  • 据我所知,通用约束是不可能的,因此没有可用的编译时检查。但是,您可以在运行时检查实际类型。
  • 你可以用重载和可选参数来做这件事,但这很讨厌。请参阅codeblog.jonskeet.uk/2010/11/02/… 如果您可以向我们提供有关您想要实现的目标的更多信息,我们可以为您提供更多帮助。
  • @sloth :我有一个 Add&lt;TValue&gt;(Func&lt;TViewModel, TValue&gt; expression) 方法,我想确保它只用于不可为空的类型(例如:Add(x =&gt; x.Id) OK Add(x =&gt; x.CreationDate.Value) OK Add(x =&gt; x.CreationDate) NOK) .

标签: c# generics nullable non-nullable generic-constraints


【解决方案1】:

正如评论中所述,您可以使用重载 参数(可以是可选的)来做到这一点。我刚才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)

【讨论】:

    【解决方案2】:

    不,在声明方面是不可能的。要么是struct,要么是class。 但是,您可以在运行时检查typeof(T) 以确保TNullable&lt;T2&gt;

    Type type = typeof(T);
    if(Nullable.GetUnderlyingType(type) == null)
        throw new Exception();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 2017-01-21
      • 1970-01-01
      • 2018-10-27
      • 2020-06-28
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      相关资源
      最近更新 更多