ページ

2012年9月3日月曜日

◆「デリゲート型ではないため ラムダ式 を型 'System.Delegate' に変換できません」

「Delegate」という機能はVer1.0の頃から判ったようでいて色々と躓く。
COBOLプログラマーにはなかなかついていけない概念だ。

ラムダ式もやっと判った気がするっと使っていると表題の様なエラーにぶつかり???となる。

今後のために表題のエラーについて、ここらで考察しておく。

一般的なイベントハンドラー
  1. public partial class Form1 : Form
  2. {
  3.     public Form1()
  4.     {
  5.         InitializeComponent();
  6.  
  7.         button1.Click += new EventHandler(button1_Click);
  8.          
  9.     }
  10.  
  11.     void button1_Click(object sender, EventArgs e)
  12.     {
  13.         MessageBox.Show("Click!!");
  14.     }
  15. }

このイベントハンドラーはラムダ式を使って以下のように書ける。

ラムダ式を使ったイベント処理
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10.  
  11. namespace WindowsFormsApplication1
  12. {
  13.     public partial class Form1 : Form
  14.     {
  15.         public Form1()
  16.         {
  17.             InitializeComponent();
  18.  
  19.             button1.Click += (sender, e) => MessageBox.Show("Lamda");
  20.              
  21.         }
  22.  
  23.         //void button1_Click(object sender, EventArgs e)
  24.         //{
  25.         //    MessageBox.Show("Click!!");
  26.         //}
  27.     }
  28. }

ラムダ式って楽ちん、っと他の場所でも使い始める。
以下はWPFのソース。

UIElement.AddHandlerサンプル
  1. public partial class MainWindow : Window
  2. {
  3.     public MainWindow()
  4.     {
  5.         InitializeComponent();
  6.         this.AddHandler(Button.ClickEvent, new RoutedEventHandler(ClickHandler));
  7.     }
  8.  
  9.     private void ClickHandler(object sender, RoutedEventArgs e)
  10.     {
  11.         txtblk1.Text = "Hello Event!!";
  12.     }

イベントハンドラーの時の感覚で行くと、このRoutedEventHandlerもラムダ式に出来そう。

ラムダ式バージョン
  1. public partial class MainWindow : Window
  2. {
  3.     public MainWindow()
  4.     {
  5.         InitializeComponent();
  6.         //this.AddHandler(Button.ClickEvent, new RoutedEventHandler(ClickHandler));
  7.         this.AddHandler(Button.ClickEvent, (sender,e) => txtblk1.Text = "Lamda");
  8.     }
  9.  
  10.     //private void ClickHandler(object sender, RoutedEventArgs e)
  11.     //{
  12.     //    txtblk1.Text = "Hello Event!!";
  13.     //}
  14.  
  15. }

しかし、残念ながらこのソースは表題のエラーとなってしまう。
「デリゲート型ではないため ラムダ式 を型 'System.Delegate' に変換できません」
一体全体何の事?

自分なりに考えて見たのだが、こういう事ではなかろうか。

まずイベントの方だが、定義はこんな感じにEventHandler型となっている。
image

EventHandler型とは、
image

となっていて、objectとEventArgsを引数にして戻り値無しのメソッドとなっている。

一方、うまくいかなかったAddHandlerメソッドの定義を見てみると、
image

確かに、Delegateを指定せよとなっている。

両者の違いを類推するに、前者は「EventHandler型」となっているので(Object sender,EventArgs e)を引数とし戻り値無しのDelegate。
Delegateとしての型が決まっているのでラムダ式から型変換が可能であり、引数と戻り値が一致したラムダ式を記述すればよい。
後者はただのDelegateなので、引数・戻り値ともに未定のDelegate。
ラムダ式からはDelegateの型が類推できない(しない)ため、明示的にDelegateの型を指定する必要がある。

よって、ラムダ式を使うのであれば以下のようにDelegateの型を指定した上で記述する。

Code Snippet
  1.     public MainWindow()
  2.     {
  3.         InitializeComponent();
  4.         //this.AddHandler(Button.ClickEvent, new RoutedEventHandler(ClickHandler));
  5.         this.AddHandler(Button.ClickEvent,  new RoutedEventHandler((sender,e) => txtblk1.Text = "Lamda"));
  6.     }
  7.  
  8.     //private void ClickHandler(object sender, RoutedEventArgs e)
  9.     //{
  10.     //    txtblk1.Text = "Hello Event!!";
  11.     //}
  12.  
  13. }

っと、素人考えながら以上のように理解しておく。

0 件のコメント:

コメントを投稿

私が最近チェックした記事