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

Why can't this method infer its parameter type from the Predicate<T> parameter in the signature?

为什么我对 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);
  }
}

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

方法组 string.IsNullOrEmpty 和 lambda i => i == 0 均未提供足够的信息来派生 ValueOrDefault<T> 调用中的 T。编译器无法使用您将类型 stringf.ValueA 传递给第一个 Func,并将类型 intf.ValueB 传递给第二个 [=17] 的事实=],因为这些是 ValueOrDefault<T> 方法的 return 值。

如果您提供一个类型,例如,通过创建一个正确类型的单独变量,您将能够编译您的代码:

Predicate<string> isNullEmpty = string.IsNullOrEmpty;
var valueA = ValueOrDefault(toSave, fromDb, isNullEmpty)(f => f.ValueA);
Predicate<int> isZero = i => i == 0;
var valueB = ValueOrDefault(toSave, fromDb, isZero)(f => f.ValueB);

Demo.