前に紹介した、コードの字面上いけてる感じのINotifyPropertyChangedの実装ですが、結構内部で色々やってるので遅いんだろうな〜となんとなく思ってました。
- INotifyPropertyChangedのいけてる実装
ということで、今日時間をはかってみました。実験したコードは以下のようなコードです。
/// 前に紹介したイケテル実装 public class IketeruEmp : INotifyPropertyChanged { private string _name; public string Name { get { return _name; } set { _name = value; PropertyChanged.Raise(() => Name); // 素敵っ } } public event PropertyChangedEventHandler PropertyChanged; } // 普通の真面目な実装 public class NormalEmp : INotifyPropertyChanged { #region INotifyPropertyChanged メンバ public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string name) { if (PropertyChanged == null) return; PropertyChanged(this, new PropertyChangedEventArgs(name)); } #endregion private string _name; public string Name { get { return _name; } set { _name = value; OnPropertyChanged("Name"); // 文字列になってしまうのよ } } }
Nameというプロパティを持つ単純なクラスです。2つあって、片方は前に紹介した方法で、もう片方は、普通の実装方法です。これを以下のようなMainメソッドを書いて速度を比較してみました。
class Program { static void Main(string[] args) { { var emp = new NormalEmp(); // とりあえず何もしないイベントを登録 emp.PropertyChanged += (sender, e) => { }; var watch = Stopwatch.StartNew(); // 1万回名前を変更してみる foreach (var i in Enumerable.Range(0, 10000)) { emp.Name = "田中" + i; } Console.WriteLine("ノーマル: {0}ms", watch.ElapsedMilliseconds); } { var emp = new IketeruEmp(); // とりあえず何もしないイベントを登録 emp.PropertyChanged += (sender, e) => { }; var watch = Stopwatch.StartNew(); // 1万回名前を変更してみる foreach (var i in Enumerable.Range(0, 10000)) { emp.Name = "田中" + i; } Console.WriteLine("イケテル: {0}ms", watch.ElapsedMilliseconds); } } }
1万回ループして、PropertyChangedイベントを発行させています。イベントハンドラは、とりあえず何もしないものを登録してあります。実行してみると・・・
ノーマル: 3ms イケテル: 1915ms
ということで、ちょっと実用するには性能を改善しないといけないみたいです・・・。
残念っ!