gpt4 book ai didi

c# - 表达式中的逆变

转载 作者:太空狗 更新时间:2023-10-29 18:32:24 25 4
gpt4 key购买 nike

我正在尝试创建一个通用 Action 委托(delegate)

  delegate void ActionPredicate<in T1, in T2>(T1 t1, T2 t2);

public static ActionPredicate<T,string> GetSetterAction<T>(string fieldName) 
{

ParameterExpression targetExpr = Expression.Parameter(typeof(T), "Target");
MemberExpression fieldExpr = Expression.Property(targetExpr, fieldName);
ParameterExpression valueExpr = Expression.Parameter(typeof(string), "value");

MethodCallExpression convertExpr = Expression.Call(typeof(Convert), "ChangeType", null, valueExpr, Expression.Constant(fieldExpr.Type));

UnaryExpression valueCast = Expression.Convert(convertExpr, fieldExpr.Type);
BinaryExpression assignExpr = Expression.Assign(fieldExpr, valueCast);
var result = Expression.Lambda<ActionPredicate<T, string>>(assignExpr, targetExpr, valueExpr);
return result.Compile();
}

这是我的来电

 ActionPredicate<busBase, string> act = DelegateGenerator.GetSetterAction<busPerson>("FirstName");

这是业务对象

 public abstract class busBase 
{

}
public class busPerson : busBase
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }

public string GetFullName()
{
return string.Format("{0} {1}", FirstName, LastName);
}
}

这是我在编译过程中得到的错误

Cannot implicitly convert type 'BusinessObjects.ActionPredicate<BusinessObjects.busPerson,string>' to 'BusinessObjects.ActionPredicate<BusinessObjects.busBase,string>'. An explicit conversion exists (are you missing a cast?)    

我的 GetSetterAction 正在返回 ActionPerdicate,这里 T 是 busPerson,我试图将它存储在 ActionPredicate 中,同时牢记逆变。但它失败了。我不知道如何进一步进行。请帮助..!

最佳答案

通用逆变允许您分配委托(delegate) D<TDerived>致代表D<TBase>由于下面说明的原因(此处使用 Action<T1>):

Action<string> m1 = MyMethod; //some method to call
Action<object> m2 = m1; //compiler error - but pretend it's not.
object obj = new object();

m2(obj); //runtime error - not type safe

如您所见,如果我们被允许执行此分配,那么我们将破坏类型安全,因为我们将能够尝试调用委托(delegate) m1通过传递和实例 object而不是 string .然而,换一种方式,即将委托(delegate)引用复制到其参数类型比源更派生的类型是可以的。 MSDN has a more complete example of generic co/contra variance .

因此您需要更改 act 的声明至 ActionPredicate<busPerson, string> act或者,更有可能的是,考虑编写 GetSetterAction始终返回 ActionPredicate<busBase, string> 的方法.如果这样做,还应该添加类型约束

where T1 : busBase

对于该方法,您还需要更改表达式的构建方式,将前两行替换如下:

ParameterExpression targetExpr = Expression.Parameter(typeof(busBase), "Target");
//generate a strongly-typed downcast to the derived type from busBase and
//use that as the type on which the property is to be written
MemberExpression fieldExpr = Expression.Property(
Expression.Convert(targetExpr, typeof(T1)), fieldName);

添加通用约束是一种很好的方式,可以确保这种向下转换对任何 T1 始终有效。 .

略有不同 - Action<T1, T2> 出了什么问题代表?它似乎和你做的完全一样? :)

关于c# - 表达式中的逆变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10101834/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com