获取变量(非硬编码)名称?

发布于 2024-08-04 10:47:48 字数 661 浏览 7 评论 0原文

我正在寻找一种检索变量名称的方法,因此我不必在需要时使用硬编码声明(对于属性名称等):

我几乎不相信这是可能的;也许有人有解决方案。 注意:即使不是变量,属性也会移动。

'Pseudo:
Module Module1

    Sub Main()
        Dim variable = "asdf"
        Dim contact As New Contact

        Dim v1 = GetVariableName(variable) 'returns variable
        Dim v2 = GetVariableName(contact.Name) 'returns Name

    End Sub

    Class Contact
        Public ReadOnly Property Name()
            Get
                Return Nothing
            End Get
        End Property
    End Class

    Public Function GetVariableName(variable As Object) As String
        ':}
    End Function

End Module

欢迎用 VB 或 C# 提供答案。

I am looking for a way to retrieve the variable name, so I don't have to use hard-coded declarations when needed (for property names etc.):

I hardly believe it's possible; maybe someone has a solution.
Note: even not variables, properties would also be a move.

'Pseudo:
Module Module1

    Sub Main()
        Dim variable = "asdf"
        Dim contact As New Contact

        Dim v1 = GetVariableName(variable) 'returns variable
        Dim v2 = GetVariableName(contact.Name) 'returns Name

    End Sub

    Class Contact
        Public ReadOnly Property Name()
            Get
                Return Nothing
            End Get
        End Property
    End Class

    Public Function GetVariableName(variable As Object) As String
        ':}
    End Function

End Module

Answers are welcommed in either VB or C#.

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

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

发布评论

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

评论(4

西瑶 2024-08-11 10:47:48

哦,有一个简单的解决方案,使用表达式树这里是一个例子,只需适应您在 c# 中的需求

string GetPropertyName<T>(Expression<Func<T>> property)
{
    MemberExpression ex = (MemberExpression)property.Body;
    string propertyName = ex.Member.Name;
    return propertyName;
}

现在您可以做到

String example = null;
String propertyName = GetPropertyName(()=>example.Length);
//propertyName == "Length"

我第一次看到它,这是一个启示! ;)

Oh there is a simple solution, use expression trees here is an example, just adapt to your needs in c#

string GetPropertyName<T>(Expression<Func<T>> property)
{
    MemberExpression ex = (MemberExpression)property.Body;
    string propertyName = ex.Member.Name;
    return propertyName;
}

Now you can do

String example = null;
String propertyName = GetPropertyName(()=>example.Length);
//propertyName == "Length"

The first time I've seen that, it was a revelation ! ;)

-残月青衣踏尘吟 2024-08-11 10:47:48

@亚伯拉罕·平祖尔;您链接到的文章中的进一步链接提供了以下代码片段:

static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}

static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
return properties[0].Name;
}

它确实生成“Name is 'args'”。 Rinat 的方法利用 C# 编译器生成的属性名称在表达式 new{args} 中生成匿名类型。完整的文章在这里:http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html --

编辑 - -

进一步阅读 Rinat 的文章后,这也可以通过生成表达式树并浏览该树或其包含的 IL 来完成。基本上,阅读链接的文章!

@Abraham Pinzur; Following a further link in the article you linked to provides this snippet:

static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}

static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
return properties[0].Name;
}

Which does produce "Name is 'args'". Rinat's method exploits the property name generated by the C# compiler to produce an anonymous type in the expression new{args}. The full article is here: http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html

--Edit--

Having read further into Rinat's article, this can also be done by producing an expression tree and browsing either the tree, or the IL it contains. Basically, read the linked article!

被翻牌 2024-08-11 10:47:48

Rinat Abdullin 是 通过从匿名方法(或 lambda 表达式)解析 IL 来执行类似的操作。他的完整内容代码在这里

因此,您的示例如下所示:

class Program
{
    static void Main (string[] args)
    {
        var variable = "asdf";

        var v1 = GetVariableName(() => variable);  // returns "variable"
    }

    static string GetVariableName (Func<object> variable)
    {   // Again, credit to Mr. Abdullin ...
        var il = variable.Method.GetMethodBody().GetILAsByteArray();
        var fieldHandle = BitConverter.ToInt32(il,2);
        var field = variable.Target.GetType()
                .Module.ResolveField(fieldHandle);
        return field.Name;
    }
}

但是,这不会直接扩展到您的第二种情况(contact.Name --> "Name")。

Rinat Abdullin is doing something like this by parsing IL from an anonymous method (or lambda expression). His full code is here.

So, your example would look like:

class Program
{
    static void Main (string[] args)
    {
        var variable = "asdf";

        var v1 = GetVariableName(() => variable);  // returns "variable"
    }

    static string GetVariableName (Func<object> variable)
    {   // Again, credit to Mr. Abdullin ...
        var il = variable.Method.GetMethodBody().GetILAsByteArray();
        var fieldHandle = BitConverter.ToInt32(il,2);
        var field = variable.Target.GetType()
                .Module.ResolveField(fieldHandle);
        return field.Name;
    }
}

However, this does not directly extend to your second case (contact.Name --> "Name").

救赎№ 2024-08-11 10:47:48

那是不可能的。发送到示例中的方法的不是变量本身,而只是变量包含的引用的副本。

该方法可以扫描所有存在的对象以查找成员变量之间的引用,但只有当变量是类成员时才可行。局部变量不可能以这种方式到达,因为它们只存在于堆栈中。此外,如果多个变量中存在相同的引用,则该方法将无法判断使用了其中的哪一个。

在您的示例中,Name 属性返回一个空引用,当然不可能知道它来自哪里。

如果变量是值类型,它将被装箱在堆上的新对象内。由于对装箱对象的唯一引用是发送到该方法的引用,并且装箱对象没有对原始对象的引用,因此无法判断哪个变量被装箱。

That's not possible. What's sent to the method in your example is not the variable itself, but only a copy of the reference that the variable contains.

The method could scan all objects that exist for the reference among member variables, but that would only be doable if the variable is a class member. Local variables are not possible to reach that way as they only exist on the stack. Also, if the same reference exist in more than one variable, the method would not be able to tell which of them was used.

In your example the Name property returns a null reference, it is of course impossible to tell where that came from.

If the variable was a value type, it would get boxed inside a new object on the heap. As the only reference to the boxed object is the one that is sent to the method, and the boxed object has no reference back to the original, there is no way of telling which variable was boxed.

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