[英]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.