代码之家  ›  专栏  ›  技术社区  ›  Amit Joshi

如何将lambda作为参数从一个函数传递到另一个函数?

c#
  •  -2
  • Amit Joshi  · 技术社区  · 8 年前

    我有以下课程(有些部分是从 here ):

    class TestExpression
    {
        public string GetValue(Expression<Func<object>> field)
        {
            string str = GetColumnName(field);
            //Do something with 'str'
            return str;//Return modified 'str'
        }
    
        public string GetColumnName<TType>(Expression<Func<TType>> field)
        {
            var me = field.Body as MemberExpression;
            if(me == null)
            {
                throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
            }
            return me.Member.Name;
        }
    }
    
    public sealed class MyClass
    {
        public static int StaticProperty { get; set; }
        public int InstanceProperty { get; set; }
    }
    

    以下是我在课堂上的使用方法:

    TestExpression te = new TestExpression();
    string name;
    name = te.GetColumnName(() => MyClass.StaticProperty);//Works correctly
    name = te.GetColumnName(() => new MyClass().InstanceProperty);//Works correctly
    
    name = te.GetValue(() => MyClass.StaticProperty);//Fail
    name = te.GetValue(() => new MyClass().InstanceProperty);//Fail
    

    如果我打电话给 GetColumnName() 功能直接,效果非常好。但是,我需要在多个位置使用此逻辑,这就是为什么我将其放在单独的函数中,并从其他函数(如 GetValue() ). 在这种情况下,它不起作用。那样的话 field.Body as MemberExpression 计算结果为 null .

    我不想暴露 GetColumnName() 像 public ; 会的 private 作用

    如何将lambda作为参数从一个函数传递到另一个函数?

    2 回复  |  直到 8 年前
        1
  •  4
  •   Patrick Hofman Wahid Bitar    8 年前

    问题是,您的C#代码实际上包含一个类型转换,您看不到它,因为在C#中,它确实发生在表达式上,因为预期的类型是 Expression<Func<object>> (请注意 object !).

    () => MyClass.StaticProperty
    

    实际上是:

    () => (object)MyClass.StaticProperty
    

    这个 (object) 零件转换为 Convert(MyClass.StaticProperty) . 突然,这不是 MemberExpression 再加上 UnaryExpression .

    您可以通过将方法设置为泛型来防止所有这一切,从而避免对 对象 :

    public string GetValue<TType>(Expression<Func<TType>> field)
    
        2
  •  1
  •   Anders Strömberg    8 年前

    将GetValue方法的签名更改为:

    public string GetValue<T>(Expression<Func<T>> field)
    

    否则,您将在属性不可见的对象上操作。