How does nameof work? - c#

I was just wondering how come nameof from C# 6, can access non static property just like if it was static. Here is an example
public class TestClass
{
public string Name { get; set; }
}
public class Test
{
public Test()
{
string name = nameof(TestClass.Name); // whats so speciall about nameof
//string name2 = TestClass.Name; this won't compile obviously,
}
}

It's not "accessing" the property - that operator is purely a compiler mechanism to inject the "name" of the argument into the code. In this case it will replace nameof(TestClass.Name) with "Name". The fact that it's non-static is irrelevant.

nameof Interpreter gets resolved at compiletime and translated to a static string instead.
In your case nameof(TestClass.Name) you will only return "Name" as a string.
You have to use nameof(TestClass).
With nameof you can minimize redundancy in your code (For instance: you dont have to define a string for a propertyname or something like this by using nameof.
You can also use it to represent a classes name. But be aware! nameof(MyClass)
may not be the same as at runtime if you have an derived class!
For runtime purposes use typeOf or .GetType() instead.
Read more at MSDN

Related

Roslyn - SyntaxGenerator, generate AutoProperty

Is it somehow possible to generate an auto-property with the Roslyn SyntaxGenerator class (NOT SyntaxFactory)?
This:
var myProperty = generator.PropertyDeclaration("MyProperty", generator.TypeExpression(SpecialType.System_String), Accessibility.Public);
will generate:
public string MyProperty {
get {
}
set {
}
}
I would like to have:
public string MyProperty { get; set; }
Is this possible with some option? I found some solutions which uses SyntaxFactory, but i would like to use SyntaxGenerator.
I don't think that is possible.
If you take a look at the source for PropertyDeclaration you will notice, that unless the getter/setter is not declared or the property is abstract any getAccessorStatements/setAccessorStatements passed as null are set to an empty IEnumerable.
The generation of the accessors-statements then uses the AccessorDeclaration which will either return the accessors with a body (if the accessor is declared as null) or with a semicolon (if it is not null which is only possible for abstract properties as noted above).
There also seems to be an open issue on github on this.

Why not explicitly initialized readonly autoimplemented property is valid in c# 6?

Update 1
It seems like either my English is terribly awful, or people just don't give a sh... to understand what I'm asking about or simply look at the title of the post.
C#5 specification clearly states:
Because the backing field is inaccessible, it can be read and written
only through the property accessors, even within the containing type.
This means that automatically implemented read-only or write-only
properties do not make sense, and are disallowed.
public string MyProperty {get;} has no sense, yet it costs nothing for compiler to emit getter not even warring about lacking setter. Backing field will be initialized with a default value. What does it mean? It means that designers spent some effort to implement a verification, to introduce functionality that could be left out.
Let's now consider C#6:
In C#6 the initialization of auto-implemented properties was introduced.
public string FirstName { get; set; } = "Jane";
or
public string FirstName { get; } = "Jane";
In the latter case property can be set in a constructor as well:
public class Program
{
public string ImagePath { get; }
public static void Main()
{
}
public Program()
{
ImagePath = "";
}
}
But only in constructor of the class where property was declared. Derived classes cannot set property's value.
Now ask yourself what this property means, if it was not initialized in constructor:
property string My {get;}
This is a 100% equivalent of C#5 prohibited property. It has no sense.
But such declaration being invalid in C#5 became valid in C#6. However semantics didn't change at all: this property is useless without explicit initialization.
That's why I am asking:
Why not explicitly initialized readonly auto-implemented property is valid in c# 6?
What I expect to see as an answer:
Either debunking of my initial assumptions about changes in C#6
Or the explanation of how and why compiler designers changed their mind
about what makes sense, and what does not.
I find the answer It's by design to be completely irrelevant. It is just a fact. I look for reasons. I don't believe compiler designers decide on changes in behavior of compiler with just tossing the coin.
This is an example of good answer.
Original question
In VS2015 this code is compiled without errors:
public class Program
{
public string ImagePath { get; }
public static void Main()
{
Console.WriteLine("Hello World");
}
}
However, in VS2013 I get error:
Compilation error (line 5, col 28): 'Program.ImagePath.get' must
declare a body because it is not marked abstract or extern.
Automatically implemented properties must define both get and set
accessors.
I know about initializable auto implemented properties, and in case of VS2015 field gets default value, that is null here. But then it's interesting to know why this snippet was invalid in C# 5?
Initializable auto-implemented readonly property left without explicit initialization seems to me a bit ODD. It is likely a mistake rather than intention. I'd personally prefer compiler to require explicit initialization in this case:
public string ImagePath { get; } = default(string);
Ok, I know that such property can be also assigned in constructor:
public class Program
{
public string ImagePath { get; }
public static void Main()
{
}
public Program()
{
ImagePath = "";
DoIt();
}
public void DoIt()
{
//ImagePath = "do it";
}
}
public class My : Program
{
public My()
{
//ImagePath = "asdasd";
}
}
But if compiler can check that local variable is not initialized, the same is possible for the property.
So why is it as it is?
The compiler is telling you that automatic properties must have both accessors defined. For example, you could fix the error with
public string ImagePath { get; private set; }
assuming that you do not intend the property to be settable outside the class.
As to why you have to declare a setter or manually implement the property -- well, what good would be a property that you can read from, but will always return the default value of its type since there is no way to set it? Conversely, what good would be a property you can write to but can neither read from nor hook into its setter?
C# 6.0 gives you the option of having write-once, read many auto-properties; this is a huge difference as the value can be arbitrarily chosen, allowing you convenient syntax for properties with immutable values.
I have no idea why your question have been down voted. This is interesting observation but please keep in mind that it is not a breaking change - it is just 'new functionality' that is 'leftover' of other functionality - initialization of auto-implemented properties.
That means it had no sense previously, but now it has.
Moreover, I think it has always had sense. E.g. when you have some base class or interface, for example
interface IPerson
{
int Age { get; }
}
Some day you may want to implement null-object pattern where the age is irrelevant. In c#5 you have to write public int Age { get { return 0; } }, while in c#6 you can simply do public int Age { get; } or even transform interface to abstract class changing only its definition from interface to abstract class.

Get property name C#

I have a class :
class Sample
{
...
}
and define a property like this:
Sample sampleParam =new Sample(...);
and have a function :
private void Func(Sample s)
{}
and use it like:
Func(sampleParam);
can I get the 's' name in the function? I mean can I get "sampleParam"(the name of param)?
It sounds odd; but I need the name of the passed param.
and sorry for this type of asking; I just wanted to ask my question as simple as possible
public string GetParamName(System.Reflection.MethodInfo method,int index)
{
string strParameterName = string.Empty;
if (method != null && method.GetParameters().Length > index)
strParameterName = method.GetParameters()[index].Name;
return retVal;
}
Yes there is a way to achieve this through Reflection...
You should never reference variable or property names from called methods - it's bad manners and bad design (mostly the latter).
There is nameof operator in C# 6.0, but it wasn't designed for this.
You could use expression trees, which would slightly change your syntax. If sampleParam is not a property but a variable, you can't really access it, because compiler does not store any references to that name in generated dll file.
This isn't exactly what you're asking for, but is perhaps closer to what you want, but you could take a look at System.Environment.StackTrace.
I think it is not possible to get the name for a variable which value is passed to a method. But there is the compiler service CallerMemberNameAttribute which copies the name of the caller method (here the get accessor of our property Name) to the calling method if not specified:
class Person {
static void Main(string[] args) {
Person bart = new Person();
bart.Name = "Bart";
Console.ReadKey();
}
private string _name;
public string Name {
get {
return _name;
} set {
_name = value;
PropertyChanged(); //no need to fill in `Name` here! :)
}
}
//automatically copy caller's name to `propertyName`, at compile time
private void PropertyChanged([CallerMemberName] string propertyName = "") {
object propertyValue = this.GetType().GetProperty(propertyName).GetValue(this);
Console.WriteLine("Property '" + propertyName + "' changed the value to '" + propertyValue + "'");
}
}
Prints:
Property 'Name' changed the value to 'Bart'
If you mean can you get the name 'sampleParam' from INSIDE func? The the answer is no. There is nameof() in C#6.0 but 'sampleParam' inside not in scope inside the func. The variable s (of type Sample) is crated and assigned a ref to sampleParam.
You can get the name "s" inside Func.
You can get the name "sampleParam" in the calling class (outside Func).
Example (available on dotnetfiddle)
using System;
public class Program
{
public static Sample sampleParam {get; set;} =new Sample();
public static void Main()
{
Console.WriteLine($"Name of property: {nameof(sampleParam)}");
Func(sampleParam);
}
private static void Func(Sample s)
{
Console.Write($"Name of parameter: {nameof(s)}");
}
}
public class Sample
{
}
Output:
Name of property: sampleParam
Name of parameter: s
Now this is a rather simplistic example. Func exists in the same class as sampleParam and there is only one property so one could derive the name but my assumption is despite your question stating it this way you are looking for a more generalized solution. The problem is that inside func the calling parameter name is not in scope. You could capture it via nameof in the calling method and pass it into func but you shouldn't that would be horrible code for a variety of reasons.
As described what you are doing is intentionally building fragile tightly coupled code which is something developers work very hard to prevent. The caller is not going to know the name of the parameter passed into func is important and shouldn't. This leads me to believe this an xy problem.

Use enum item name like an attribute parameter

I just want don't use "Managers" for each attribute and use some enum for that.
But it seems it is impossible or I am wrong?
So I try to replace
[RequiresRole("Managers")]
with
[RequiresRole(HardCodedRoles.Managers.ToString())]
...
public enum HardCodedRoles
{
Administrators,
Managers
}
How about a class instead of an enum, making the class static to avoid somebody new:ing it ?
public static class HardCodedRoles
{
public const string Managers = "Managers";
public const string Administrators = "Administrators";
}
[RequiresRole(HardCodedRoles.Managers)]
You could also use the nameof keyword, i.e.:
[RequiresRole(nameof(HardCodedRoles.Managers))]
The reason you see the error is because ToString() is a method and thus the value cannot be calculated at compile time.
If you can use [RequiresRole(HardCodedRoles.Managers)] instead, you can perform the ToString elsewhere in your code, and this could give you the functionality you need. This will require that you change the parameter of your attribute from string to HardCodedRoles.
(I would imagine that using a const won't work, because the type of the parameter will still be string, so the input won't be restricted.)

How to refactor when reflection is used to get methods by name?

Suppose I get a MethodInfo in the following way:
Assembly assembly = Assembly.Load(assemblyName);
Type type = assembly.GetType(nameSpaceName+"."+className);
MethodInfo mi = type.GetMethod("myMethod", bf); // bf are the binding flags.
But later I decide to change the case/name of myMethod.
Is there a way to either:
Refactor so that it changes the name in the string.
Change the reflection call so it gets the method without using the method's name as a string?
The reason for this is so I can test my code which requires the use of reflection, but I'd rather not require that nobody ever change the name of the methods in the code.
If you use Visual Studio to do the refactoring, there is an option to search literal strings and comments for the name and change those too. I highly recommend using the preview when using that option, though, to verify that you're only changing the parts you expect.
Of course, you could use a constant like internal const string methodName = "methodName"; so that you only have the literal string once. You could manually change the one string literal when you refactor the method name. You'd also be able to rename the methodName more easily.
You could use a custom attribute, and decorate your methods with this attribute. Then instead of getting the method by its name, you could get it by the ID defined in the attribute. That way the method name could change as often as it needs to...just a thought.
[AttributeUsage(AttributeTargets.Method)]
public class CustomMethodAttribute : Attribute
{
public string ID { get; set; }
}
Usage:
[CustomMethodAttribute(ID = "UniqueIDHere")]
public void Test()
{
}
Do you have a concrete reference to the type in question?
Even if you don't have it explicitly, you can make the method generic.
public void TestMethod<TargetType>(object o)
{
if (typeof(TargetType).IsAssignableFrom(o.GetType())) {
TargetType strongType = o as TargetType;
strongType.myMethod();
}
}
In fact, you could do this without reflection at all:
public void TestMethod<TargetType>(object o)
{
if (o is TargetType) {
TargetType strongType = o as TargetType;
strongType.myMethod();
}
}
For methods and properties try using expression trees.
You can get reflection-related information from them, saving compile-time checking and enabling automatic refactoring.
I believe you can get assembly-related information and namespace names as well.
Just write several helper functions which can retrieve such information from expression trees.
You can find several helper functions here
They allow write such code:
FirePropertyChanged(() => PropertyName);
which is the same as
FirePropertyChanged("PropertyName");

Categories

Resources