.net core 中的 Func delegate 是如何进行逆变工作的
How does contravariance work with Func delegate in .net core
我有以下代码,我试图为我的域对象编写通用验证规则。在这样做的同时我有一个问题来处理 Func delegate supporting variance
public class Person { }
public class Employee : Person { }
internal interface IValidation<T> where T: Person
{
void AddValidationRule(Func<T,bool> predicateFunction);
}
internal class BaseValidation : IValidation<Person>
{
void IValidation<Person>.RegisterValidationRules(Person person)
{
}
}
internal class EmployeeValidation : BaseValidation
{
void RegisterValidation()
{
Func<Employee,bool> empPredicate = CheckJoiningDate;
base.AddValidationRule(empPredicate);
}
bool CheckJoiningDate(Employee employee)
{
return employee.JoiningDate > DateTime.Now.AddDays(-1) ;
}
}
有了上面的代码,编译器会给出一条错误消息说
Compiler Error on line : base.AddValidationRule(empPredicate);
Argument 1: cannot convert from 'System.Func<>Employee, bool>' to
'System.Func<>Person, bool>
我已经提到了这个 https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/dd465122%28v%3dvs.100%29 但我仍然无法让编译器理解这里的逆变,
感谢您的帮助,让我更好地理解这一点
cannot convert from 'System.Func<>Employee, bool>' to 'System.Func<>Person, bool>
base.AddValidationRule
需要一个可以对任何 Person
进行操作的函数。您的功能只能在 Exployee
上运行,这更具限制性。这是错误的方差形式。
此处未显示,但可能 BaseValidation
已实施 IValidation<Person>
。
可能,最好的解决方法是确保您从 IValidation<Employee>
继承,可能是通过使 BaseValidation
通用。
这行得通吗?
internal class BaseValidation<T> : IValidation<T>
{
void IValidation<T>.RegisterValidationRules(T entity)
{
}
}
internal class EmployeeValidation : BaseValidation<Employee>
{
//...
}
你混淆了协变和逆变。
通过协变,泛型类型参数可以 "smaller" 超出要求。也就是说,如果我们有:
Func<Mammal, Mammal> f1 = whatever;
Func<Mammal, Animal> f2 = f1;
为什么这样行得通? Func
在其第二个参数中是 协变 。 f2
期待 returns Animal
的代表。它得到了一个returns smaller 类型的代表; Mammal
比 Animal
少,所以 Mammal
更小 。
想想为什么会这样。当有人呼叫 f2 时,他们希望找回动物。但如果他们真的调用 f1,他们仍然得到一个动物,因为每个哺乳动物都是动物。
通过协变,泛型类型的 "size" 与类型参数的大小 在同一方向 上变化。 Mammal
小于 Animal
。 Func<Mammal, Mammal>
小于 Func<Mammal, Animal>
。这就是为什么它是 "co" 方差,co meaning "together".
逆变是相反的,因此"contra",意思是"against"。使用逆变,泛型类型参数可以比预期的更大:
Func<Giraffe, Mammal> f3 = f1;
f3 需要一个带长颈鹿的函数;我们有一个函数需要更大的类型,哺乳动物。它更大,因为哺乳动物比长颈鹿多。逆变说这很好,那应该是有道理的。如果有人用长颈鹿调用 f3,如果这实际上是对 f2 的调用也没关系,因为 f2 可以带长颈鹿;它可以带走任何哺乳动物。
你混淆了协变和逆变;您期望可以以协变方式使用逆变参数,这是错误的。接受雇员的函数不能转换为接受人员的函数,因为您可以将非雇员人员传递给它。接受员工的函数可以转换为接受经理的函数,因为所有经理都是员工。
我有以下代码,我试图为我的域对象编写通用验证规则。在这样做的同时我有一个问题来处理 Func delegate supporting variance
public class Person { }
public class Employee : Person { }
internal interface IValidation<T> where T: Person
{
void AddValidationRule(Func<T,bool> predicateFunction);
}
internal class BaseValidation : IValidation<Person>
{
void IValidation<Person>.RegisterValidationRules(Person person)
{
}
}
internal class EmployeeValidation : BaseValidation
{
void RegisterValidation()
{
Func<Employee,bool> empPredicate = CheckJoiningDate;
base.AddValidationRule(empPredicate);
}
bool CheckJoiningDate(Employee employee)
{
return employee.JoiningDate > DateTime.Now.AddDays(-1) ;
}
}
有了上面的代码,编译器会给出一条错误消息说
Compiler Error on line : base.AddValidationRule(empPredicate); Argument 1: cannot convert from 'System.Func<>Employee, bool>' to 'System.Func<>Person, bool>
我已经提到了这个 https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/dd465122%28v%3dvs.100%29 但我仍然无法让编译器理解这里的逆变,
感谢您的帮助,让我更好地理解这一点
cannot convert from 'System.Func<>Employee, bool>' to 'System.Func<>Person, bool>
base.AddValidationRule
需要一个可以对任何 Person
进行操作的函数。您的功能只能在 Exployee
上运行,这更具限制性。这是错误的方差形式。
此处未显示,但可能 BaseValidation
已实施 IValidation<Person>
。
可能,最好的解决方法是确保您从 IValidation<Employee>
继承,可能是通过使 BaseValidation
通用。
这行得通吗?
internal class BaseValidation<T> : IValidation<T>
{
void IValidation<T>.RegisterValidationRules(T entity)
{
}
}
internal class EmployeeValidation : BaseValidation<Employee>
{
//...
}
你混淆了协变和逆变。
通过协变,泛型类型参数可以 "smaller" 超出要求。也就是说,如果我们有:
Func<Mammal, Mammal> f1 = whatever;
Func<Mammal, Animal> f2 = f1;
为什么这样行得通? Func
在其第二个参数中是 协变 。 f2
期待 returns Animal
的代表。它得到了一个returns smaller 类型的代表; Mammal
比 Animal
少,所以 Mammal
更小 。
想想为什么会这样。当有人呼叫 f2 时,他们希望找回动物。但如果他们真的调用 f1,他们仍然得到一个动物,因为每个哺乳动物都是动物。
通过协变,泛型类型的 "size" 与类型参数的大小 在同一方向 上变化。 Mammal
小于 Animal
。 Func<Mammal, Mammal>
小于 Func<Mammal, Animal>
。这就是为什么它是 "co" 方差,co meaning "together".
逆变是相反的,因此"contra",意思是"against"。使用逆变,泛型类型参数可以比预期的更大:
Func<Giraffe, Mammal> f3 = f1;
f3 需要一个带长颈鹿的函数;我们有一个函数需要更大的类型,哺乳动物。它更大,因为哺乳动物比长颈鹿多。逆变说这很好,那应该是有道理的。如果有人用长颈鹿调用 f3,如果这实际上是对 f2 的调用也没关系,因为 f2 可以带长颈鹿;它可以带走任何哺乳动物。
你混淆了协变和逆变;您期望可以以协变方式使用逆变参数,这是错误的。接受雇员的函数不能转换为接受人员的函数,因为您可以将非雇员人员传递给它。接受员工的函数可以转换为接受经理的函数,因为所有经理都是员工。