为什么C#中没有`fieldof`或`methodof`运算符?

Sam*_*ell 43 c# reflection

它们可以如下使用:

FieldInfo field = fieldof(string.Empty);
MethodInfo method1 = methodof(int.ToString);
MethodInfo method2 = methodof(int.ToString(IFormatProvider));
Run Code Online (Sandbox Code Playgroud)

fieldof 可以编译为IL为:

ldtoken <field>
call FieldInfo.GetFieldFromHandle
Run Code Online (Sandbox Code Playgroud)

methodof 可以编译为IL为:

ldtoken <method>
call MethodBase.GetMethodFromHandle
Run Code Online (Sandbox Code Playgroud)

无论何时使用typeof运算符,您都可以获得完美的查找所有引用结果.不幸的是,一旦你去了田野或方法,你最终会遇到令人讨厌的黑客攻击.我想你可以做以下事情......或者你可以回去按名字命名.

public static FieldInfo fieldof<T>(Expression<Func<T>> expression)
{
    MemberExpression body = (MemberExpression)expression.Body;
    return (FieldInfo)body.Member;
}

public static MethodInfo methodof<T>(Expression<Func<T>> expression)
{
    MethodCallExpression body = (MethodCallExpression)expression.Body;
    return body.Method;
}

public static MethodInfo methodof(Expression<Action> expression)
{
    MethodCallExpression body = (MethodCallExpression)expression.Body;
    return body.Method;
}

public static void Test()
{
    FieldInfo field = fieldof(() => string.Empty);
    MethodInfo method1 = methodof(() => default(string).ToString());
    MethodInfo method2 = methodof(() => default(string).ToString(default(IFormatProvider)));
    MethodInfo method3 = methodof(() => default(List<int>).Add(default(int)));
}
Run Code Online (Sandbox Code Playgroud)

Mag*_*tLU 35

实际上,您可以避免同时使用反射和lambdas(.NET Framework 2.0).考虑以下课程:

public class methodof<T>
{
    private MethodInfo method;

    public methodof(T func)
    {
        Delegate del = (Delegate)(object)func;
        this.method = del.Method;
    }

    public static implicit operator methodof<T>(T methodof)
    {
        return new methodof<T>(methodof);
    }

    public static implicit operator MethodInfo(methodof<T> methodof)
    {
        return methodof.method;
    }
}
Run Code Online (Sandbox Code Playgroud)

它的用法:

MethodInfo writeln = (methodof<Action>)Console.WriteLine;
MethodInfo parse = (methodof<Func<string, int>>)int.Parse;
Run Code Online (Sandbox Code Playgroud)

  • +1对于一个非常优雅的解决方案,加上样式点来重载转换操作符,使其看起来更加内置.现在,如果只有C#允许我们在属性上显式引用get/set访问器,那么这也适用于那些. (4认同)

Jas*_*son 22

Eric Lippert(关于C#设计团队)在这里对此主题进行了很好的概述/讨论.报价:

这是一个非常棒的功能,几乎所有参与设计过程的人都希望我们能做到,但我们选择不这样做有很好的实际原因.如果有一天设计它并实施它是我们可以花费有限预算的最佳方式,我们就会这样做.在此之前,请使用Reflection.

  • 'Foof'会更恰当的咒骂:) (4认同)

Ter*_*nce 6

@ 280Z28 - 当我找到你的问题和代码时,我们只是坐下来弄清楚如何做到这一点.我们需要一个PropertyOf方法,所以我添加了它.在这里,万一其他人需要它.感谢这个伟大的问题.

     public static PropertyInfo PropertyOf<T>(Expression<Func<T>> expression)
    {
        MemberExpression body = (MemberExpression)expression.Body;
        PropertyInfo pi = body.Member as PropertyInfo;
        if (pi != null)
        {
            return pi;
        }
        else throw new ArgumentException("Lambda must be a Property.");
    } 

      [TestMethod()]
    public void MethodofPropertyOfTest<T>()
    {

        string foo = "Jamming";
        MethodInfo method1 = ReflectionHelper.Methodof(() => default(string).ToString());
        PropertyInfo prop = ReflectionHelper.PropertyOf(() => default(string).Length);
        Assert.AreEqual(method1.Invoke(foo, null), "Jamming");
        Assert.AreEqual(prop.GetGetMethod().Invoke(foo, null), foo.Length);
    }
Run Code Online (Sandbox Code Playgroud)

  • 如果在生产代码中需要这种类型的操作,需要注意的事项 - 对methodof,fieldof或propertyof的调用返回的值对于给定的输入是常量.每当我在一个类中需要它们时,我要么有一个静态只读字段,我初始化为FieldInfo/MethodInfo/PropertyInfo,或者我使用一个合适的`Dictionary <Type,MemberInfo>`map.如果你看一下表达式tree sugar生成的IL,你可以看到你不想运行它,除非你必须这样做.我认为将它们作为语言运算符的第一个优势是IL可以/将非常简洁. (3认同)