表达式树-Action<;T>;在C#和VB.NET中

本文关键字:VB NET -Action lt 表达式 gt | 更新日期: 2023-09-27 18:03:38

给定一段简单的代码,它可以在VB.NET:中返回属性的名称

Function NameForProperty(Of T)(ByVal field As Expression(Of Action(Of T))) As String
    Dim expression = DirectCast(field.Body, MemberExpression)
    Return expression.Member.Name
End Function

它是这样工作的:

NameForProperty(Of String)(Function (s) s.Length) ' ==> returns "Length"

我认为在C#中应该是等价的:

string NameForProperty<T>(Expression<Action<T>> field)
{
    var expression = (MemberExpression)field.Body;
    return expression.Member.Name;
}

当我尝试调用C#版本时:

NameForProperty<string>(s=>s.Length);

它返回一个编译器错误:

仅分配、调用、递增、递减和新对象表达式可以用作语句

我的问题是:这两段代码之间有什么区别?

编辑

Ivan提供了一个关于为什么代码在C#中不起作用的答案。我仍然很好奇为什么它能在VB.NET.中工作

编辑#2

需要明确的是,我并不是在寻找有效的代码——这只是为什么这些代码可以在VB.NET而不是C#中工作。

表达式树-Action<;T>;在C#和VB.NET中

public static class TypeMember<TClass>
{
    public static string PropertyName<TProp>(Expression<Func<TClass, TProp>> expression)
    {
        var body = expression.Body as MemberExpression;
        if (body == null)
            throw new ArgumentException("'expression' should be a property expression");
        return body.Member.Name;
    }
}
var propName = TypeMember<string>.PropertyName(s => s.Length);

您的版本的问题在于您正在尝试使用Action<T>。它不返回任何内容,因此lambda的主体(s.Length(应该是一个语句。事实上,这并不是一个声明。所以编译器抱怨它。

如果你写了,它也会以同样的方式抱怨

public void A()
{
    string s = "abc";
    s.Length;
}

这是一样的事情。

我不是VB.NET的专家,所以我不能解释为什么它在VB中工作,对不起。

我会尝试将方法更改为Func而不是Action

正如错误所说,你的陈述是无效的。如果您将Action更改为Func,这是可以的,因为Length是返回值。也许VB编译器还有其他检查/要求。