为什么这个方法不能从签名中的Predicate <t>参数推断出它的参数类型?</t>

时间:2015-01-23 03:52:27

标签: c# generics type-inference

为什么我的ValueOrDefault来电可以根据使用情况推断出类型?

class Foo {
  public string ValueA { get; set; }
  public int ValueB { get; set; }
}

class Example {
  // neither Func<T,bool> or Predicate<T> works
  Func<Func<Foo,T>,T> ValueOrDefault<T>(Foo orig, Foo toReplace, Predicate<T> replaceIf) {
    return getValue => {
      var origValue = getValue(orig);
      var replaceWith = getValue(toReplace);
      return replaceIf(origValue) ? replaceWith : origValue;
    };
  }

  public Response SaveSomeStuff(int clientId, Foo toSave) {
    Foo fromDb = _dbService.GetFooByClientId(clientId);
    var valueA = ValueOrDefault(toSave, fromDb, string.IsNullOrEmpty)(f => f.ValueA);
    var valueB = ValueOrDefault(toSave, fromDb, i => i == 0)(f => f.ValueB);

    var request = new Request {
      ValueA = valueA,
      ValueB = valueB,
    };
    return GetResponse(request);
  }
}

1 个答案:

答案 0 :(得分:2)

不允许C#编译器使用方法的返回值来解析方法本身,包括任何类型推断。

方法组string.IsNullOrEmpty和lambda i => i == 0都没有提供足够的信息来在T调用中派生ValueOrDefault<T>。编译器无法使用这样的事实:您将f.ValueA类型string传递给第一个Func,将f.ValueB类型int传递给第二个{{1}因为这些是Func方法的返回值。

如果你提供一个类型,例如,通过创建一个正确类型的单独变量,你就可以编译你的代码:

ValueOrDefault<T>

Demo.