接受Expression <Func <T >>表达式作为参数的扩展方法

Mat*_*ius 12 c# lambda extension-methods expression .net-4.5

我正在使用.NET4.5,C#我想创建扩展方法,允许我传递对象的属性,如果该对象的Id为0,return null否则返回该属性值.

我可以做反射没问题,所以考虑更多的训练练习而不是我试图解决实际问题.

目前扩展方法正在static课堂上看起来像这样:

    public static object GetNullIfNotSet(this WillAnswer answer, Expression<Func<WillAnswer>> expression)
    {
        if (answer.Id == 0) return null;
        return expression.Compile()();
    }
Run Code Online (Sandbox Code Playgroud)

我希望能够使用它的方式如下(答案是类型WillAnswer):

var emptyIfNewObject = answer.GetNullIfNotSet(o => o.HasBusinessAssets)
Run Code Online (Sandbox Code Playgroud)

但它给我编译错误:

错误1委托'System.Func'不带1个参数C:\ hg\Website\Areas\Wills\ViewModel\Answers.cs 38 59网站 在此输入图像描述

这让我皱眉,因为我不认为我传递任何论据(是吗?).可以取悦比我自己更聪明的人解释我的哪些期望是错误的.

万一我不清楚,我会重申.我要的是能够打电话 var emptyIfNewObject = answer.GetNullIfNotSet(o => o.HasBusinessAssets),并得到null,如果Id的answer是0.

hai*_*770 14

Expression根本不需要,只需使用Func<WillAnswer, TProp>:

public static TProp GetNullIfNotSet<TProp>(this WillAnswer answer, Func<WillAnswer, TProp> func)
{
    if (answer.Id == 0) return default(TProp);
    return func(answer);
}
Run Code Online (Sandbox Code Playgroud)

请注意,这并不总是返回,null而是默认值(如果属性是值类型).

更新(根据您的要求):

为了能够返回null所有传递的属性,方法签名已更改为返回object:

public static object GetNullIfNotSet<TProp>(this WillAnswer answer, Func<WillAnswer, TProp> func)
{
    if (answer.Id == 0) return null;
    return func(answer);
}
Run Code Online (Sandbox Code Playgroud)

但是,你将失去泛型的好处,你最终会得到明确的演员Nullable<T>:

var emptyIfNewObject = (bool?)answer.GetNullIfNotSet(o => o.HasBusinessAssets)
Run Code Online (Sandbox Code Playgroud)

哪个不太理想.


Dmi*_*nko 7

看来你需要一个Func<WillAnswer, T>不是表达式:

  public static T GetDefaultIfNotSet<T>(this WillAnswer answer, Func<WillAnswer, T> func) {
    if (null == answer)   
      throw new ArgumentNullException("answer");
    else if (null == func)   
      throw new ArgumentNullException("func");

    return answer.Id == 0 ? return default(T) : func(answer);
  }
Run Code Online (Sandbox Code Playgroud)

编辑:如果你想确保 null你可以限制泛型T:

     public static T GetNullIfNotSet<T>(this WillAnswer answer, Func<WillAnswer, T> func) 
       where T: class { // no structs here
         if (null == answer)   
           throw new ArgumentNullException("answer");
         else if (null == func)   
           throw new ArgumentNullException("func");

         return answer.Id == 0 ? return null : func(answer);
     } 
Run Code Online (Sandbox Code Playgroud)

  • @Matas Vaitkevicius:`null`是类的默认*; 例如``default(typeof(Object))`是`null`而``default(typeof(int))`是'0` (2认同)
  • @Matas Vaitkevicius:如果你想要*true*,*false*,*null*(即*nullabe boolean*)看看`Boolean?`; `default(typeof(Boolean?))`是*null* (2认同)