It's really useful for ArgumentException
and its derivatives:
public string DoSomething(string input)
{
if(input == null)
{
throw new ArgumentNullException(nameof(input));
}
...
Now if someone refactors the name of the input
parameter the exception will be kept up to date too.
It is also useful in some places where previously reflection had to be used to get the names of properties or parameters.
In your example nameof(T)
gets the name of the type parameter - this can be useful too:
throw new ArgumentException(nameof(T), $"Type {typeof(T)} does not support this method.");
Another use of nameof
is for enums - usually if you want the string name of an enum you use .ToString()
:
enum MyEnum { ... FooBar = 7 ... }
Console.WriteLine(MyEnum.FooBar.ToString());
> "FooBar"
This is actually relatively slow as .Net holds the enum value (i.e. 7
) and finds the name at run time.
Instead use nameof
:
Console.WriteLine(nameof(MyEnum.FooBar))
> "FooBar"
Now .Net replaces the enum name with a string at compile time.
Yet another use is for things like INotifyPropertyChanged
and logging - in both cases you want the name of the member that you're calling to be passed to another method:
// Property with notify of change
public int Foo
{
get { return this.foo; }
set
{
this.foo = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Foo));
}
}
Or...
// Write a log, audit or trace for the method called
void DoSomething(... params ...)
{
Log(nameof(DoSomething), "Message....");
}
T
before. There was a way to get the used type before. – Homansnameof
. Also helps to prevent typos. – Morass[Test, TestCaseSource(typeof(MyDataClass), "TestCases")]
, which can be replaced with[Test, TestCaseSource(typeof(MyDataClass), nameof(MyDataClass.TestCases))]
. Much nicer. – Bak