簡體   English   中英

獲取傳遞給 C# 方法的參數名稱

[英]Get names of the params passed to a C# method

void MyMethod(string something, params object[] parameters)
    {
      foreach (object parameter in parameters)
      {
        // Get the name of each passed parameter
      }
    }

例如,如果我按以下方式調用該方法,我想獲取名稱“myFirstParam”和“anotherParam”。

string myFirstParam = "some kind of text";
string anotherParam = 42;
MyMethod("test", myFirstParam, anotherParam);

也許反思是答案? 也許這是不可能的? 我知道這個問題的存在,但該解決方案在這里不起作用。

(請不要回答“這不是一個好主意”。那不是我的問題。)

這完全不可能。

以下是一些甚至沒有意義的案例:

MyMethod("abc", new object[5]);
MyMethod("abc", "def");
MyMethod("abc", var1 + var2);
MyMethod("abc", SomeMethod());
MyMethod("abc", b ? a : c);
MyMethod("abc", new object()); 
MyMethod("abc", null);

實際上,局部變量名甚至沒有編譯到程序集中。

以@shingo 的回答為基礎。

從 C#10 開始,您可以使用CallerArgumentExpressionAttribute Class 獲取傳遞的變量的名稱。

這是.NET6:

using System.Runtime.CompilerServices;

void F(object arg1, [CallerArgumentExpression("arg1")] string arg1Exp = "?")
    => Console.WriteLine($"{arg1Exp} => {arg1}");

var var1 = "C#10";
var var2 = "_";
var b = var1.Length > 7;

F(var1);
F(new object[5]);
F("def");
F(var1 + var2);
F(SomeMethod());
F(b ? var1 : var2);
F(new object()); 
F(null);
F(int.Parse(var1.Substring(2)) switch {
     >= 10 => "Supported",
     _ => "Not supported"
});

int SomeMethod() => 7 + 8;

Output(看起來很神奇):

var1 => C#10
new object[5] => System.Object[]
"def" => def
var1 + var2 => C#10_
SomeMethod() => 15
b ? var1 : var2 => _
new object() => System.Object
null => 
int.Parse(var1.Substring(2)) switch {
     >= 10 => "Supported",
     _ => "Not supported"
} => Supported

C# 10 引入了新屬性CallerArgumentExpressionAttribute

params參數中獲取名稱仍然是不可能的,但如果你有固定數量的參數(如重載方法),那么它是可能的。

void MyMethod(object p0,
    [CallerArgumentExpression("p0") string p0exp = "p0")
{
    Console.WriteLine(p0exp);
}

void MyMethod(object p0, object p1,
    [CallerArgumentExpression("p0") string p0exp = "p0",
    [CallerArgumentExpression("p1") string p1exp = "p1")
{
}

除了SLaks的答案之外 - 變量名在運行時根本不可用。 變量由堆棧槽表示,並由索引尋址。 因此,即使您提供的示例也無法獲取此信息,更不用說SLaks提供的所有這些示例。 反思在這里沒有幫助。 沒有什么是。

這是不可能的,我想知道你為什么需要它。

那這個呢;

void MyMethod(string something, object parameters)
{
RouteValueDictionary dic = HtmlHelper.AnonymousObjectToHtmlAttributes(options);
}

MyMethod("test", new { @myFirstParam=""some kind of text", anotherParam=42);

這已在System.Web.MVC.Html InputExtension中實現。

我的靈感在我的代碼中使用了這種技術。 它非常靈活。

不要打擾輔助方法中的“Html”命名。 與幫助器方法中的html或html屬性無關。

它只是將命名的匿名參數轉換為RouteValueDictionary,這是一個具有IDictionary<string,object> interface的特殊字典,其中key包含參數名稱,object是參數的值。

使用反射和@Martin的null參數測試示例:

using System.Reflection;

public SomeMethod(ClassA a, ClassB b, ClassC c)
{
    CheckNullParams(MethodBase.GetCurrentMethod(), a, b, c);
    // do something here
}

訪問參數名稱:

public void CheckNullParams(MethodBase method, params object[] args)
{
    for (var i=0; i < args.Count(); i++)
    {
        if (args[i] == null)
        {
            throw new ArgumentNullException(method.GetParameters()[i].Name);
        }
    }
}

這適用於構造函數和公共方法,但我沒有測試VS中的單元測試,因此可能存在一些運行時JIT問題(閱讀上面引用的文章)。

編輯:剛剛注意到,這與鏈接答案基本相同。

我從死亡中提出這個問題!

查看C#6.0的新名稱()運算符。 它可以讓你完全按照自己的意願行事,但實際上並不總是一個壞主意。

一個很好的用例是Argument Exceptions或INotifyPropertyChanged。 (特別是當你在混合中獲得繼承)

例:

interface IFooBar
{
    void Foo(object bar);
}

public class FooBar : IFooBar
{


    public void Foo(object bar)
    {
        if(bar == null)
        {
            //Old and Busted
            //throw new ArgumentException("bar");

            //The new HOTNESS
            throw new ArgumentException(nameof(bar)); // nameof(bar) returns "bar"

        }

        //....
    }

}

現在,如果您在接口IFooBar中的方法'Foo'上重命名參數'bar',您的參數異常將相應地更新(防止您忘記更改“bar”字符串)

實際上非常整潔!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM