表达式树 - Action的不同编译器行为在 C# 和 VB.NET 中

发布于 2024-11-26 05:41:59 字数 1107 浏览 0 评论 0原文

给定一段简单的代码,它可以返回 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);

它返回编译器错误:

仅限赋值、调用、递增、递减和新建对象 表达式可以用作语句

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

编辑

伊万提供了回答为什么代码在 C# 中不起作用。我仍然好奇为什么它能在 VB.NET 中工作。

EDIT#2

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

Given a simple piece of code which can return the name of a property in 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

Which works like this:

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

And what I thought would have been the equivalent in C#:

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

    return expression.Member.Name;
}

When I try to call the C# version:

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

It returns a compiler error:

Only assignment, call, increment, decrement, and new object
expressions can be used as a statement

My question is: what is the difference between the two pieces of code?

EDIT

Ivan has provided an answer as to why the code does not work in C#. I am still curious as to why it does work in VB.NET.

EDIT#2

To be clear, I'm not looking for code which works -- simply why the code would work in VB.NET and not C#.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半暖夏伤 2024-12-03 05:41:59
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。它不返回任何内容,因此 lambda 的主体 (s.Length) 应该是一个语句。这实际上不是一个声明。所以编译器会抱怨它。

如果你写的是 It is the same thing,它也会以同样的方式抱怨

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

不过,我不是 VB.NET 方面的专家,所以我无法解释为什么它可以在 VB 中工作,抱歉。

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);

The problem with your version lies in the fact that you're trying to use Action<T>. It returns nothing and thus lambda's body (s.Length) should be a statement. And it is not a statement actually. So compiler complains about it.

It would complain in the same way if you'd wrote

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

It is the same thing.

I'm not an expert in VB.NET though, so I can't explain why it is working in VB, sorry.

何时共饮酒 2024-12-03 05:41:59

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

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

I would try changing the method to Func instead of Action.

Your statement is not valid as the error says. If you change the Action to Func it's ok, because Length is the return value.
Maybe the VB compiler has other checks / requirements.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文