I’m a lambda newbie, so if I’m missing vital information in my description please tell me. I’ll keep the example as simple as possible.
I’m going over someone else’s code and they have one class inheriting from another. Here’s the derived class first, along with the lambda expression I’m having trouble understanding:
class SampleViewModel : ViewModelBase
{
private ICustomerStorage storage = ModelFactory<ICustomerStorage>.Create();
public ICustomer CurrentCustomer
{
get { return (ICustomer)GetValue(CurrentCustomerProperty); }
set { SetValue(CurrentCustomerProperty, value); }
}
private int quantitySaved;
public int QuantitySaved
{
get { return quantitySaved; }
set
{
if (quantitySaved != value)
{
quantitySaved = value;
NotifyPropertyChanged(p => QuantitySaved); //where does 'p' come from?
}
}
}
public static readonly DependencyProperty CurrentCustomerProperty;
static SampleViewModel()
{
CurrentCustomerProperty = DependencyProperty.Register("CurrentCustomer", typeof(ICustomer),
typeof(SampleViewModel), new UIPropertyMetadata(ModelFactory<ICustomer>.Create()));
}
//more method definitions follow..
Note the call to NotifyPropertyChanged(p => QuantitySaved) bit above. I don’t understand where the “p” is coming from.
Here’s the base class:
public abstract class ViewModelBase : DependencyObject, INotifyPropertyChanged, IXtremeMvvmViewModel
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged<T>(Expression<Func<ViewModelBase, T>> property)
{
MvvmHelper.NotifyPropertyChanged(property, PropertyChanged);
}
}
There’s a lot in there that’s not germane to the question I’m sure, but I wanted to err on the side of inclusiveness.
The problem is, I don’t understand where the ‘p’ parameter is coming from, and how the compiler knows to (evidently?) fill in a type value of ViewModelBase from thin air?
For fun I changed the code from ‘p’ to ‘this’, since SampleViewModel inherits from ViewModelBase, but I was met with a series of compiler errors, the first one of which statedInvalid expression term '=>' This confused me a bit since I thought that would work.
Can anyone explain what’s happening here?
The lambda
p => QuantitySavedis an expression of typeExpression<Func<ViewModelBase, int>>. Since the methodNotifyPropertyChangedis looking for an expression of<ViewModelBase, T>, it fits.So the compiler is able to infer that
pis aViewModelBase.pdidn’t “come from” anywhere, it’s basically being declared right here. It’s a parameter for the lambda. It’s going to be filled in when someone uses thepropertyparameter of your method. For example, if you put your lambda into a separate variable calledlambda, you could call it withlambda(this)and it would return theQuantitySavedvalue.The reason you can’t use
thisin the lambda is because it’s expecting a parameter name, andthisisn’t a valid name. The point is that you could call it on any instance ofViewModelBase, not just the one that created the lambda.