MVVM CallerMemberName and "magic strings" - c#

New C# 5.0 release introduced something to get rid of "magic strings" in INotifyPropertyChanged implementation like:
OnPropertyChanged("CustomerName");
Now it is possible to write just:
OnPropertyChanged();
It is possible due to CallerMemberName in method definition:
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{ ... }
It is much more refactoring friendly than "magic strings" way and faster than lambda expressions, but I wonder how can we call multiple times OnPropertyChanged from one set accessor. For example if we wanted something like this:
public int Width
{
get
{
return width;
}
set
{
width = value;
OnPropertyChanged("Width");
OnPropertyChanged("Height");
}
}
How can we do this with CallerMemberName way and avoid using "magic strings" and lambda expressions?
I also wonder how can we avoid using "magic strings" in IDataError info:
public string Error
{
get;
private set;
}
public string this[string columnName]
{
get
{
if (columnName == "Name")
{
if (String.IsNullOrWhiteSpace(Name))
Error = "Name cannot be null or empty.";
else
Error = null;
}
return Error;
}
}
I am new to MVVM so maybe I overlooked some clever way to deal with "magic strings", however I did some research and found nothing.

The simple answer is, that you can't do that. As the name CallerMemberName indicates, it will contain the name of the caller.
For cases where you want to raise PropertyChanged for another than the current one, you will have to use one of the "old" ways.
In IDataErrorInfo you also have to use one of those ways, there is no alternative.

I know this question is about C# 5.0, but if people still have questions of thise nature please check out c# 6.0. C# 6.0 Has a great way to solve this problem. Check out the nameof keyword. I wrote a little post about it if anyone is interested: c# 6.0 solves magic strings problem

This will help:
"Kind Of Magic"
Effortless INotifyPropertyChanged
http://visualstudiogallery.msdn.microsoft.com/d5cd6aa1-57a5-4aaa-a2be-969c6db7f88a
as an example for adding it to one property:
[Magic]
public string Name { get { return _name; } set { _name = value; } }
string _name;
Another example for adding it to all the class properties:
[Magic]
public class MyViewModel: INotifyPropertyChanged
{
public string Name { get; set; }
public string LastName { get; set; }
.....
}

Related

What is the purpose of private member with public getter and setter? c# [duplicate]

This question already has answers here:
Any reason to use auto-implemented properties over manual implemented properties?
(7 answers)
Closed 5 years ago.
what is the different between writing the getter and setter directly like this:
public string Name {get; set;}
and like this:
private string _name;
public string Name
{
get
{
return this._name;
}
set
{
this._name = value;
}
}
I saw that in lots of codes. why they use a private member than a public getter and setter.
is it for performance or privacy or what is the point?
thank you.
what is the different between writing the getter and setter directly
like this
public string Name {get; set;}
They're essentially the same.
The code below you're basically creating the private field and providing both getters and setters for it, which of course does the intended idea. However, the language implementors decided they could make the life of a programmer easier by providing a shorter syntax where you can create a private field and at the same time provide a getter or setter or both.
private string _name;
public string Name
{
get
{
return this._name;
}
set
{
this._name = value;
}
}
So, in C# 3 they(language implementors) came up with the idea of making the syntax shorter by enabling a programmer to simultaneously create a private field and at the same time provide a getter or setter or both.
Behind the scenes, all that happens for the code below is the compiler creates a private field and also provides a getter and setter for it. So, basically, it's shorter more concise syntax to achieve the same task as the example above.
auto-implemented property
public string Name {get; set;}
There is none.
The thing is: auto-implemented properties weren't available until C# 3 (if you look at the documentation referenced: it goes back to VS 2008 which was released with C# 3), and not all code was written in the C# 3 era. Also, not all developers are aware of this feature. If I would stumble across this kind of code, I would rewrite it to use auto-implemented properties.
An property is just a short hand and will create at the background an public get method and a public set method and a private field to store the value.
Example Code
// example property
public string Name { get; set; }
// at run time it is the same as:
private string Name;
public string GetName(){
return this.Name;
}
public string SetName(string name){
this.Name = name;
}
See Image :
The sample class only has an property in code Name.
If you use Reflection to get all the members off the Sample class you will see that at run time set_name() and get_name() methods are generated.
These methods are not specified in in code.
Short answer, there isn't a difference. The compiler will convert the "auto" property to that style regardless, it's just saving you the writer a few keystrokes. It really only comes into play when you start working with DataBinding or having to do something else in the Set portion.
private string _name;
public string Name
{
get
{
return this._name;
}
set
{
this._name = value;OnPropertyChange();
}
}
In WPF/XAML/DataBinding, this would let anyone subscribed to this object know that a property with the name "Name" has changed and it should reflect so in the UI.
The first one is called an auto-implemented property.
Second one is used when you want to add some custom code logic that validates the value in your setter.
You can control what happens in the getter & setters, whereas if the member was public, the variable could be modified directly.
private string _name;
public string Name
{
get
{
return this._name + " likes chocolate";
}
set
{
this._name = value;
}
}
Here, your private _name always stays the same, but anyone accessing Name will get _name + " likes chocolate".
In the setter, you could do some validation.

call PropertyChange with public member, not string C#

I've looked around a bit online and wasn't able to easily find a solution to what i was looking for. It may be in part to me not being sure the terminology to search for.
I wanted to know is there a way to call the PropertyChanged event using the property member name like so...
private string height;
public string Height
{
get { return name; }
set
{
Set(ref height, value);
RaisePropertyChanged( ()=> Name);
}
}
rather than using the actual string which can be seen here..
private string height;
public string Height
{
get { return name; }
set
{
Set(ref height, value);
RaisePropertyChanged("Name");
}
}
Raise Event
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
I've attempted a solution to this, but wasn't able to come to a conclusion. I know there are methods out there somewhere and im sure there are more modern ways to do this. Its 2016!!
Since you appear to be using C# 6, you can use the nameof operator, which resolves the name of the referenced property at compile time, passing a string to your method.
RaisePropertyChanged(nameof(Name));
If you need to use an earlier C# compiler, you can resolve the name of the property through a lambda expression; this is what Entity Framework does for its Include operator. You can define a GetPropertyName utility method (see example), then call it like so:
RaisePropertyChanged(GetPropertyName(() => Name));

C# data model, are there any differences between using these form?

I'm going to build my MVC Web Application and I created my data models.
I found online many ways to compile a data model code. This is easiest one, using only public properties:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
But I also found a version using a private variable and a public properies, like this:
public class Person
{
private int id;
private string firstName;
private string lastName;
public int Id { get { return id; } set { id = value; } }
public string FirstName { get { return firstName; } set { firstName = value; } }
public string LastName { get { return lastName; } set { lastName = value; } }
}
What is the difference between these two data models?
When is more advisable using the first one or the second one?
This is the same like asking: what is a difference bwteen auto properties and normal properties.
Auto properties:
easy creation (less to type)
internal field is generated for you automatically by compiler
Not possible to debug (set a break point inside the property)
Normal properties
Sligtly more code to type
Easy to debug
More code can be injected inside get and set
If first example compiler will create private field for every automatic property itself, but they behave exactly the same. More info on MSDN
I would suggest second approach as you have more control how property works, but there is nothing wrong in using first one.
The fiest block you have are auto-properties, and under the hood the c# will be compiled similar to the second block, so in this case there is no difference. Take a look at these posts here:
C# 3.0 auto-properties - useful or not?
What are Automatic Properties in C# and what is their purpose?
Any reason to use auto-implemented properties over manual implemented properties?
If you were implementing the INotifyPropertyChanged interface, then you would need to use the traditional way as you would be interacting with the property in the setter, see example...
http://msdn.microsoft.com/en-us/library/ms743695.aspx

How to write MVVM properties?

With MVVM I always see these both methods for properties:
private int myProperty;
public int MyProperty
{
get { return myProperty; }
set
{
myProperty = value;
NotifyPropertyChanged("MyProperty");
}
}
and
private int myProperty;
public int MyProperty
{
get { return myProperty; }
set
{
myProperty = value;
NotifyPropertyChanged(m => m.MyProperty);
}
}
The first one use an hardcoded string to NotifyPropertyChanged and the second one use a lambda expression to NotifyPropertyChanged. I don't want to create a debate to ask what is the better solution but I would like to understand what are the differences bewteeen these two solution. What are the consequences of using one or the other?
Correct me if I'm wrong but the lambda expression solution should use more memory and should be slower than the hardcoded string because the NotifyPropertyChanged method of the base class use delegate and reflection. But the hardcoded string solution may create stupid bug because it's a string and nothing to tell me I correctly wrote it.
The second expression would either generate a compiler error on the property name change, or would automatically change with it (via the Rename support in VS or ReSharper).
So basically, you gain compiler support for property names. The wrong name provided to the notify would mean that data-binding would break. With string names, this breakage would be silent.
In a small UI the choice is irrelevant in my opinion, but in a large application with a heavy UI layer the extra support against bugs can pay itself off in the long run.
Performance won't be problematically slower, don't forget, binding is reflection-powered anyway. Performance, as always, is relative. The hard-coded version will technically be faster because it doesn't need to reflect the property name out of the meta-data. How much faster, I'm not sure.
Rather than repeating that code of NotifyPropertyChanged for every property, I felt the below code is more cleaner
Create a Set method in your ViewModel Base
protected bool Set<T>(Expression<Func<T>> selectorExpression, ref T field, T value)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
RaisePropertyChanged(selectorExpression);
return true;
}
and use them as
string title;
public string Title
{
get { return title; }
set { Set(() => Title, ref title, value); }
}
I use the following method in a base class implementing INotifyPropertyChanged and it is so easy and convenient:
public void NotifyPropertyChanged()
{
StackTrace stackTrace = new StackTrace();
MethodBase method = stackTrace.GetFrame(1).GetMethod();
if (!(method.Name.StartsWith("get_") || method.Name.StartsWith("set_")))
{
throw new InvalidOperationException("The NotifyPropertyChanged() method can only be used from inside a property");
}
string propertyName = method.Name.Substring(4);
RaisePropertyChanged(propertyName);
}

what is the automatic variable name of an auto-implemented properties

I'm trying to do this:
public string LangofUser
{
get
{
return string.IsNullOrEmpty("how to get value?") ? "English" : "how to get value?";
}
set;
}
do I have to do this?
string _LangofUser
public string LangofUser
{
get
{
return string.IsNullOrEmpty(_LangofUser) ? "English" : _LangofUser;
}
set { _LangofUser = value};
}
This mixing of auto-implement and not-auto-implemented properties in C# is not possible. A property must be fully auto-implemented or a normal property.
Note: Even with a fully auto-implemented property there is no way to reference the backing field from C# source in a strongly typed manner. It is possible via reflection but that's depending on implementation details of the compiler.
As others have said, don't try to mix automatic and regular properties. Just write a regular property.
If you want to know what secret names we generate behind the scenes for hidden compiler magic, see
Where to learn about VS debugger 'magic names'
but do not rely on that; it can change at any time at our whim.
If you provide your own implementation of the property, it's not automatic any more. So yes, you need to do create the instance.
Check this question
What's the difference between encapsulating a private member as a property and defining a property without a private member?
If you want to keep the automatic property and still have a default value, why don't you initialize it in your constructor?
public class MyClass
{
public MyClass() { LangOfUser = "English"; }
public string LangOfUser { get; set; }
}
Since C# 6, you can also set a default value for a property as follows:
public class MyClass
{
public string LangOfUser { get; set; } = "English";
}

Categories