アプリ版:「スタンプのみでお礼する」機能のリリースについて

using System;
using System.Drawing;
using System.Windows.Forms;

class PaintHello
{
public static void Main()
{
Form form = new Form();

form.Text = "Paint Hello";

form.BackColor = Color.White;

form.Paint += new PaintEventHandler(MyPaintHandler);

Application.Run(form);

}
static void MyPaintHandler(object objSender,PaintEventArgs pea)
{
Form form = (Form)objSender;//←この部分が分かりません。
Graphics grfx = pea.Graphics;

grfx.DrawString("Hello,world!", form.Font, Brushes.Black, 0, 0);
}
}

C#の勉強をしているのですが、イベントを発生させるためにデリゲートに自分で作ったメソッドを
引数として送るというのは理解できるのですが、
このMyPaintHandlerのobject objSender という部分が、書籍の説明だと「objSenderはForm型のオブジェクトなのでキャストはうまくいく」
と書かれています。

object型というのを調べるとSystem名前空間にObjectというクラスがあるのですが、これはすべてのクラスのルートであり、、、とMSDNに書かれていて、なぜForm型と言えるのかわかりません。

そもそもこのキャストはなぜ必要なのでしょう。お願いします。

A 回答 (4件)

> object objsender のobjectという型は


> すべてのクラスのルートであるという System.Object のObjectの部分でしょうか?
> 先頭が小文字なので別物でしょうか?

class Program {
public static void Main() {
System.Console.WriteLine(typeof(string));
System.Console.WriteLine(typeof(object));
System.Console.WriteLine(typeof(int));
}
}

それぞれ System.String, System.Object, System.Int32 の alias(別名) です。

この回答への補足

もう少し質問させてください。

System.Console.WriteLine(typeof(object));

が System.Object; のエイリアス、ということは、

object objSender のobjectという型は??

http://msdn.microsoft.com/ja-jp/library/9kkx3h3c …

↑のURLにあるobjectでという型で良いですか?

補足日時:2014/01/08 21:53
    • good
    • 0

>つまりobjsender はどんなものにもキャスト可能、と思って良いですか?



いいえ。
キャスト可能なのは、そのインスタンスのクラスやその親クラス、実装インターフェイスなどだけです。
なので厳密には

if (objsender is Form) {
Form form = (Form)objsender;

}

のようにobjsenderがFormかどうか確認した上でキャストします。
もしくは

// objsenderがFormにキャスト不可能なときにはformにはnullが設定される
Form form = objsender as Form;
    • good
    • 1
この回答へのお礼

貴重な回答ありがとうございます。ベストアンサーにしたいと思いましたが
それと同様と思ってください。ありがとうございます。

お礼日時:2014/01/09 21:13

一般的なことをいえば、イベントハンドラに渡されたsender(ここではobjSender)がForm型であるとはかぎりません。


なぜなら、イベントハンドラをイベントとして処理するのではなく、直接呼び出すこともできてしまうからです。

ただ、今回のケースに限っていえば、MyPaintHandlerメソッドはprivateで他のクラスから呼ばれる可能性はなく、Form.Paintに登録しているので、Form型のオブジェクトがobjectに変換されて渡されることが期待できるということです。
厳密なことをいえば、"Paint Hello"というフォームのタイトルを頼りにするなどしてformのインスタンスを見つけ出し、Paintイベントを漁ってMyPaintHandlerを取り出した上で直接呼び出すといったこともできるでしょうから、やや無防備なのは確かですが...

キャストが必要なのは、FormクラスのFontプロパティを使うためです。
Formではなくobject型のままではFormクラスのプロパティにアクセスすることはできません。

この回答への補足

ありがとうございます。Fontプロパティを使うためのキャスト、理解しました。

もう少し質問させてください。その右側にある object objsender のobjectという型は

すべてのクラスのルートであるという System.Object のObjectの部分でしょうか?

先頭が小文字なので別物でしょうか?

つまりobjsender はどんなものにもキャスト可能、と思って良いですか?

補足日時:2014/01/08 18:57
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
検証プログラムをいろいろやってみて大変勉強になりました。
もう少しC#の挙動を理解する必要があるようです。
またよろしくお願いいたします。

お礼日時:2014/01/09 21:30

>object型というのを調べるとSystem名前空間にObjectというクラスがあるのですが、これはすべてのクラスのルートであり、、、とMSDNに書かれていて、なぜForm型と言えるのかわかりません。



鍵は

>form.Paint += new PaintEventHandler(MyPaintHandler);

です。
formがPaintイベントを呼び出すときform自身をsenderとして渡します。
MyPaintHandlerはformのPaintイベントからしか呼び出されるように設定されていませんからMyPaintHandlerの第1引数のobjSenderのインスタンスはformなのでForm型ということになります。

>そもそもこのキャストはなぜ必要なのでしょう。お願いします。

ObjectのままだとFormのメソッドやプロパティが使えないからです。
    • good
    • 0
この回答へのお礼

ObjectクラスのままだとFormのメソッドやプロパティが使えない、ということは理解できました。
質問なのですが、object objSender の部分のobjectという型宣言は、
System.ObjectクラスのObjectと同じ者でよいですか?
oの文字が小文字と大文字で違うものをさしてはないでえしょうか?

お礼日時:2014/01/07 23:04

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!