Il existe de bons articles qui suggèrent différentes manières de mettre en œuvre INotifyPropertyChanged
.
Considérez l'implémentation de base suivante:
class BasicClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void FirePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
private int sampleIntField;
public int SampleIntProperty
{
get { return sampleIntField; }
set
{
if (value != sampleIntField)
{
sampleIntField = value;
FirePropertyChanged("SampleIntProperty"); // ouch ! magic string here
}
}
}
}
Je voudrais le remplacer par celui-ci:
using System.Runtime.CompilerServices;
class BetterClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Check the attribute in the following line :
private void FirePropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
private int sampleIntField;
public int SampleIntProperty
{
get { return sampleIntField; }
set
{
if (value != sampleIntField)
{
sampleIntField = value;
// no "magic string" in the following line :
FirePropertyChanged();
}
}
}
}
Mais parfois je lis que le [CallerMemberName]
l'attribut a de mauvaises performances comparé aux alternatives. Est-ce vrai et pourquoi? Utilise-t-il la réflexion?
Non, l'utilisation de [CallerMemberName]
n'est pas plus lent que l'implémentation de base supérieure.
En effet, selon cette page MSDN ,
Les valeurs de l’appelant sont émises littéralement dans le langage intermédiaire (IL) lors de la compilation.
Nous pouvons vérifier cela avec n'importe quel désassembleur IL (comme ILSpy ): le code pour l'opération "SET" de la propriété est compilé exactement de la même manière:
Donc, pas d'utilisation de la réflexion ici.
(exemple compilé avec VS2013)