简体   繁体   English

从该方法中获取变量调用方法的名称

[英]Get name of variable calling method from within that method

I want to create an extension method for objects that check to see if the object is null and throw an exception if it is. 我想为对象创建一个扩展方法,检查对象是否为null并抛出异常(如果是)。 I want to keep the original variable name though. 我想保留原始变量名称。 Can I somehow get it from within the extension method? 我可以以某种方式从扩展方法中获取它吗? It is "cumbersome" to have to write customer.NotNull("customer") vs customer.NotNull() . 必须编写customer.NotNull("customer") vs customer.NotNull()是“麻烦的”。

No, unfortunately you can't. 不,不幸的是你不能。 Variable names are not part available at run time. 变量名在运行时不可用。 However, you can use expressions like this: 但是,您可以使用以下表达式:

void NotNull<T>(Expression<Func<T>> expression)
{
    var me = expression.Body as MemberExpression;
    var name = me.Member.Name;
    var value = expression.Compile().Invoke();
    ...
}


NotNull(() => customer);
// using System.Diagnostics.Contracts;
using System.Linq.Expressions;

static void ThrowIfNull<T>(Expression<Func<T>> expr) where T : class
{
    // Contract.Requires(expr != null);
    // Contract.Requires(expr.Body.NodeType == ExpressionType.MemberAccess);
    if (((object)expr.Compile().Invoke()) == null)
    {
        throw new ArgumentNullException(((MemberExpression)expr.Body).Member.Name);
    }
}

Then call it like this: 然后像这样称呼它:

object someVariable = null;
ThrowIfNull(() => someVariable);  // will throw an ArgumentNullException 
                                  // with paramName == "someVariable"

PS: I am not sure whether this is a good idea: There will be an overhead for first building an expression tree, and then compiling it each time this method is called, just so that you can check whether the variable contains a null reference, and if so, retrieve the variable name. PS:我不确定这是否是一个好主意:首先构建一个表达式树,然后每次调用此方法时都会编译它,这样就可以检查变量是否包含null引用,如果是,则检索变量名称。 Something like void ThrowIfNull<T>(T arg, string paramName) is not as nice, but is likely o perform much better! void ThrowIfNull<T>(T arg, string paramName)的东西不是很好,但可能会表现得更好!

As the other said, but note that compiling an expression is something slow... So this variant receives the value as a parameter. 正如另一个所说,但请注意,编译表达式是很慢的......所以这个变量接收值作为参数。 You have to write more, but for methods that are called hundred of times, it could be better. 你必须写更多,但对于被称为百次的方法,它可能会更好。

[DebuggerHidden]
public static void NotNull<T>(T value, Expression<Func<T>> exp) where T : class
{
    if (value != null)
    {
        return;
    }

    var body = exp.Body as MemberExpression;

    if (body == null)
    {
        throw new ArgumentException("Wrongly formatted expression");
    }

    throw new ArgumentNullException(body.Member.Name);
}

Usage: 用法:

NotNull(str, () => str);

The [DebuggerHidden] is so that the debugger won't step into the method. [DebuggerHidden]是调试器不会进入该方法的。 In the end if the method throws, normally it's because what you passed, not what there is in the method. 最后,如果方法抛出,通常是因为你传递的内容,而不是方法中的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM