<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2652296181611976813</id><updated>2024-09-16T08:51:58.643+09:00</updated><category term="C#"/><category term="WebBrowser"/><category term="delegate"/><category term="デリゲート"/><category term="HTML"/><category term="HTTP"/><category term="Load イベント"/><category term="UserControl"/><category term="WSH"/><category term="WebRequest"/><category term="enum"/><category term="where"/><category term="アプリケーション構成ファイル"/><category term="イベント"/><category term="クローン"/><category term="ソース"/><category term="ディープコピー"/><category term="デザインパターン"/><category term="マルチスレッド"/><category term="型制約"/><category term="拡張メソッド"/><category term="非同期"/><title type='text'>C# 備忘録</title><subtitle type='html'>主に C# についての自分メモです。</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-8879550809768595520</id><published>2009-09-27T04:52:00.009+09:00</published><updated>2009-09-30T13:02:08.946+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Load イベント"/><category scheme="http://www.blogger.com/atom/ns#" term="UserControl"/><category scheme="http://www.blogger.com/atom/ns#" term="WebBrowser"/><title type='text'>UserControl の Load イベントハンドラーが呼ばれない</title><content type='html'>.NET Framework2.0 SP2、.NET Framework3.5 SP1 で試したところ&lt;br /&gt;
UserControl に WebBrowser コントロールを貼り付けると、&lt;br /&gt;
Load イベントハンドラーが呼ばれません。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
private void UserControl1_Load(object sender, EventArgs e)
{
    MessageBox.Show(&quot;呼ばれない orz&quot;);
}
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
このデリゲート(UserControl1_Load) を呼ぶのは、&lt;br /&gt;
ベースクラスの OnLoad() メソッドです。&lt;br /&gt;
というわけで、OnLoad() が呼ばれないのかな？と思い、&lt;br /&gt;
オーバーライドしてブレークを張ったところ、ちゃんと呼ばれています。&lt;br /&gt;
&lt;br /&gt;
OnLoad() で追加したイベントハンドラーを呼ばれないなんてことがあるの？&lt;br /&gt;
など思いつつ Reflector で UserControl.OnLoad() を覗いてみました。&lt;br /&gt;
実装は次のようになっています。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
protected virtual void OnLoad(EventArgs e)
{
  EventHandler handler = (EventHandler)base.Events[EVENT_LOAD];
  if (handler != null)
  {
    handler(this, e);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
実際、OnLoad() でブレイクして&lt;br /&gt;
base.Events[EVENT_LOAD] をウォッチしてみると&lt;br /&gt;
やっぱり null になっていました。&lt;br /&gt;
これで、イベントハンドラーが呼ばれないのも納得です。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;だって呼んでいないんだもの (T ^ T)&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
では、なぜ呼ばれないか？&lt;br /&gt;
ブレイク張ってみると一目瞭然。張るところは当然&lt;br /&gt;
&lt;br /&gt;
1.) this.Load += new System.EventHandler(this.UserControl1_Load);&lt;br /&gt;
2.) UserControl1.OnLoad()&lt;br /&gt;
&lt;br /&gt;
UserControl に WebBrowser を貼り付けなければ&lt;br /&gt;
1 -&amp;gt; 2 と正しい順序で動きます。&lt;br /&gt;
一方、WebBrowser を張ると、2 -&amp;gt; 1 の順番で動きます。&lt;br /&gt;
どうやら this.Load += ... より前に&lt;br /&gt;
OnLoad() を呼んでしまう処理があるようです。&lt;br /&gt;
InitializeComponent() の先頭でブレイクし、&lt;br /&gt;
ステップ実行していくと・・・ありました。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
this.Controls.Add(this.webBrowser1);
&lt;/code&gt;&lt;/pre&gt;この後、UserControl1.OnLoad() が実行されてしまいました。&lt;br /&gt;
&lt;br /&gt;
Refrelctor で今度は ControlCollection.Add() メソッドを覗いてみました。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
public virtual void Add(Control value)
{
  if (value != null)
  {
    if (value.GetTopLevel())
    {
      throw new ArgumentException(SR.GetString(&quot;TopLevelControlAdd&quot;));
    }
    if (this.owner.CreateThreadId != value.CreateThreadId)
    {
      throw new ArgumentException(SR.GetString(&quot;AddDifferentThreads&quot;));
    }
    Control.CheckParentingCycle(this.owner, value);
    if (value.parent == this.owner)
    {
      value.SendToBack();
    }
    else
    {
      if (value.parent != null)
      {
        value.parent.Controls.Remove(value);
      }
      base.InnerList.Add(value);
      if (value.tabIndex == -1)
      {
        int num = 0;
        for (int i = 0; i &amp;lt; (this.Count - 1); i++)
        {
          int tabIndex = this[i].TabIndex;
          if (num &amp;lt;= tabIndex)
          {
            num = tabIndex + 1;
          }
        }
        value.tabIndex = num;
      }
      this.owner.SuspendLayout();
      try
      {
        Control parent = value.parent;
        try
        {
          value.AssignParent(this.owner);
        }
        finally
        {
          if ((parent != value.parent) &amp;amp;&amp;amp; ((this.owner.state &amp;amp; 1) != 0))
          {
            value.SetParentHandle(this.owner.InternalHandle);
            if (value.Visible)
            {
              &lt;span style=&quot;background-color: #93c47d;&quot;&gt;value.CreateControl();
&lt;/span&gt;            }
          }
        }
        value.InitLayout();
      }
      finally
      {
        this.owner.ResumeLayout(false);
      }
      LayoutTransaction.DoLayout(this.owner, value, PropertyNames.Parent);
      this.owner.OnControlAdded(new ControlEventArgs(value));
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
先ほど、&lt;br /&gt;
&lt;blockquote&gt;&lt;i&gt;&lt;br /&gt;
このデリゲート(UserControl1_Load) を呼ぶのは、&lt;br /&gt;
ベースクラスの OnLoad() メソッドです。&lt;br /&gt;
&lt;/i&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
なんて言いましたが、では OnLoad() はどこから呼ばれるか？&lt;br /&gt;
答えは、UserControl.OnCreateControl() です。&lt;br /&gt;
となると、なんとなく怪しいのがマーカーを入れた value.CreateControl() で、&lt;br /&gt;
Visible プロパティを見て分岐していることから&lt;br /&gt;
実際、以下のようにすると UserControl1_Load が呼ばれるようになります。&lt;br /&gt;
それならと試しに、WebBrowser を継承して&lt;br /&gt;
OnCreateControl() をオーバーライドし、&lt;br /&gt;
base.OnCreateControl() を呼ぶ直前に Visible = false とすると&lt;br /&gt;
UserControl1_Load は呼ばれませんでした。残念。。orz&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
this.webBrowser1.Visible = false;
this.Controls.Add(this.webBrowser1);
this.webBrowser1.Visible = true;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
てっきり WebBrowser の OnCreateControl() から&lt;br /&gt;
コンテナコントロールの OnCreateControl() を呼んでいるのだと&lt;br /&gt;
思ったのですが、見当違いだったみたいです。&lt;br /&gt;
&lt;br /&gt;
間違いなく ControlCollection.Add() のどこかで&lt;br /&gt;
コンテナコントロールの OnCreateControl() が呼ばれるはずなのですが&lt;br /&gt;
長くなりすぎたし、とりあえずは解決できているので良しとします。</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/8879550809768595520/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/usercontrol-load.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/8879550809768595520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/8879550809768595520'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/usercontrol-load.html' title='UserControl の Load イベントハンドラーが呼ばれない'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-8332729539226961518</id><published>2009-09-26T00:39:00.000+09:00</published><updated>2009-09-26T00:39:42.046+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="delegate"/><category scheme="http://www.blogger.com/atom/ns#" term="デリゲート"/><category scheme="http://www.blogger.com/atom/ns#" term="マルチスレッド"/><category scheme="http://www.blogger.com/atom/ns#" term="非同期"/><title type='text'>非同期デリゲート</title><content type='html'>.net では Thread、タイマーなどマルチスレッドを実現する方法が&lt;br /&gt;
いくつか用意されています。&lt;br /&gt;
今回のデリゲートもそのうちのひとつで、&lt;br /&gt;
スレッドの優先順位など細かい制御はできないものの、&lt;br /&gt;
任意の型のパラメーターをいくつでも渡せたり、&lt;br /&gt;
戻り値が簡単に取れるのはなにかと使い勝手がよいと思います。&lt;br /&gt;
&lt;br /&gt;
実際の使用例は以下の通りです。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
&lt;span class=&quot;comment&quot;&gt;// 何かするデリゲート&lt;/span&gt;
delegate string SomeDelegate();
private void button1_Click(object sender, EventArgs e)
{
    &lt;span class=&quot;comment&quot;&gt;// デリゲートの実装&lt;/span&gt;
    SomeDelegate some = new SomeDelegate(delegate
    {
        &lt;span class=&quot;comment&quot;&gt;// 5 秒後 &quot;hoge&quot; を返します。&lt;/span&gt;
        System.Threading.Thread.Sleep(5000);
        return &quot;hoge&quot;;
    });

    &lt;span class=&quot;comment&quot;&gt;// SomeDelegate を非同期に呼び出します。&lt;/span&gt;
    IAsyncResult ar = some.BeginInvoke(null, null);

    &lt;span class=&quot;comment&quot;&gt;// SomeDelegate から戻り値を得ます。&lt;/span&gt;
    Console.WriteLine(&quot;returned : &quot; + some.EndInvoke(ar));
}
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
ボタンを押して 5 秒後、出力ウィンドウに&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;returned : hoge&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
と出力されます。&lt;br /&gt;
&lt;br /&gt;
ただし、上の例では EndInvoke() をメインスレッドで&lt;br /&gt;
呼び出すことになるので、デリゲートが実行されている間&lt;br /&gt;
せっかく非同期に呼び出したのにメインスレッドが停止してしまいます。&lt;br /&gt;
(今回の場合、フォームが固まります。)&lt;br /&gt;
できればこれは避けたいので、少し実装に手間が増えますが&lt;br /&gt;
コールバック関数を用意します。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
{
    &lt;span class=&quot;comment&quot;&gt;/* BeginInvoke() の直前まで同じなので省略 */&lt;/span&gt;

    &lt;span class=&quot;comment&quot;&gt;// AsyncCallback デリゲート&lt;/span&gt;
    AsyncCallback callback = new AsyncCallback(some_Completed);

    &lt;span class=&quot;comment&quot;&gt;// 第一引数にコールバックメソッドを指定します。&lt;/span&gt;
    IAsyncResult ar = some.BeginInvoke(callback, null);
}

&lt;span class=&quot;comment&quot;&gt;// SomeDelgate の終了時にコールされます。&lt;/span&gt;
private void some_Completed(IAsyncResult async)
{
    &lt;span class=&quot;comment&quot;&gt;// AsyncResult にキャストします。&lt;/span&gt;
    AsyncResult asyncResult = (AsyncResult)async;

    &lt;span class=&quot;comment&quot;&gt;// AsyncDelegate で SomeDelegate のインスタンスが取得できます。&lt;/span&gt;
    SomeDelegate some = (SomeDelegate)asyncResult.AsyncDelegate;
    Console.WriteLine(&quot;returned : &quot; + some.EndInvoke(async));
}
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
メインスレッドでデリゲートの完了を待たないので&lt;br /&gt;
処理自体は先ほどと同じですが、フォームが固まることはありません。&lt;br /&gt;
&lt;br /&gt;
最後になりましたが、デリゲート自体は ThreadPool を利用した技術なので&lt;br /&gt;
同時実行数には制限があります。&lt;br /&gt;
場合によってはデッドロックが発生することもあるそうなのですが、&lt;br /&gt;
特に必要に迫られたことがないのでこの辺あんまり調べていないです。&lt;br /&gt;
まぁそんな依存のある非同期処理ならコールバックで&lt;br /&gt;
次の非同期処理を BeginInvoke すればよいかと思います。</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/8332729539226961518/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post_26.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/8332729539226961518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/8332729539226961518'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post_26.html' title='非同期デリゲート'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-7468720165171233666</id><published>2009-09-15T15:49:00.003+09:00</published><updated>2009-09-15T16:01:51.418+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="クローン"/><category scheme="http://www.blogger.com/atom/ns#" term="ディープコピー"/><title type='text'>ディープコピー</title><content type='html'>オブジェクトをディープコピーする方法です。&lt;br /&gt;
コピーする型には SerializableAttribute 属性をつける必要があります。&lt;br /&gt;
コピーが不要なフィールドには NonSerializedAttribute 属性をつけることで&lt;br /&gt;
シリアライズの対象から除外されます。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
[SerializableAttribute()]
public class SerializableClass
{
  public int SerializableField;

  &lt;span class=&quot;comment&quot;&gt;// このフィールドはコピーされません。&lt;/span&gt;
  [NonSerializedAttribute()]
  public int NonSerializableField;

  public SerializableClass Clone()
  {
    object clone;
    using (MemoryStream stream = new MemoryStream())
    {
      BinaryFormatter formatter = new BinaryFormatter();
      formatter.Serialize(stream, this);
      stream.Position = 0;
      clone = formatter.Deserialize(stream);
    }
    return clone as SerializableClass;
  }
}&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
使いかたは以下のとおりです。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
SerializableClass serializable = new SerializableClass();
serializable.SerializableField = 10;
serializable.NonSerializableField = 100;

SerializableClass clone = serializable.Clone();

&lt;span class=&quot;comment&quot;&gt;// i には 10 が代入されます。&lt;/span&gt;
int i = clone.SerializableField;
&lt;span class=&quot;comment&quot;&gt;// j には 0 が代入されます。(コピーされません)&lt;/span&gt;
int j = clone.NonSerializableField;
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
もちろん clone オブジェクトのプロパティを変更しても、&lt;br /&gt;
コピー元の serializable オブジェクトのプロパティは変更されません。&lt;br /&gt;
&lt;br /&gt;
いろいろな型のクローンが必要なら次のようなヘルパークラスを用意すると&lt;br /&gt;
いいかもしれません。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
public class CloneHelper
{
  public static T Clone&amp;lt;T&amp;gt;(T target)
  {
    object clone = null;
    using (MemoryStream stream = new MemoryStream())
    {
      BinaryFormatter formatter = new BinaryFormatter();
      formatter.Serialize(stream, target);
      stream.Position = 0;
      clone = formatter.Deserialize(stream);
    }
    return (T)clone;
  }
}

次のようにクローンメソッドを定義します。

[SerializableAttribute()]
public class SerializableClass
{
  public SerializableClass Clone()
  {
    return CloneHelper.Clone&amp;lt;serializableclass&amp;gt;(this);
  }
}
&lt;/code&gt;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/7468720165171233666/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post_15.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/7468720165171233666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/7468720165171233666'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post_15.html' title='ディープコピー'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-920601919555521251</id><published>2009-09-14T16:52:00.001+09:00</published><updated>2009-09-14T16:53:51.226+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="WSH"/><category scheme="http://www.blogger.com/atom/ns#" term="ソース"/><title type='text'>HTML ソースを見る</title><content type='html'>C# とは関係ないですが、&lt;br /&gt;
指定した URL の HTML ソースを見るスクリプト (WSH) です。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: red;&quot;&gt;(*) Excel, Firefox がインストールされている必要があります。&lt;/span&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
try {
    var excel = WScript.CreateObject(&quot;Excel.Application&quot;);
    var result = excel.InputBox(&quot;source viewer&quot;, &quot;URL&quot;, &quot;http://&quot;);
    excel.Quit();

    &lt;span class=&quot;comment&quot;&gt;// Firefox のパスです。ご自身の環境に合わせて書き換えてください。&lt;/span&gt;
    var browser = &quot;C:\\Program Files\\Mozilla Firefox\\firefox.exe&quot;;
    var shell= WScript.CreateObject(&quot;WScript.Shell&quot;);
    shell.Run(&quot;\&quot;&quot; + browser + &quot;\&quot; -url &quot; + &quot;view-source:&quot; + result);
} catch (e) {
}&lt;/code&gt;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/920601919555521251/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/c-url-html-wsh-excel-firefox-try-var.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/920601919555521251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/920601919555521251'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/c-url-html-wsh-excel-firefox-try-var.html' title='HTML ソースを見る'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-5213797281648571581</id><published>2009-09-10T11:31:00.003+09:00</published><updated>2009-09-10T11:35:25.492+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="拡張メソッド"/><title type='text'>拡張メソッド</title><content type='html'>C#3.0 から既存の型のインスタンスメソッドのように振舞う&lt;br /&gt;
拡張メソッドが追加されました。&lt;br /&gt;
使い方の一例として、String クラスにメソッドを追加してみます。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
public static class StringExtensions
{
    // 指定された String オブジェクトが null
    // または Empty 文字列であるかどうかを示します。
    public static bool IsNullOrEmpty(this String s)
    {
        return String.IsNullOrEmpty(s);
    }
}
&lt;/code&gt;
&lt;/pre&gt;文字列の null or Empty を評価するメソッドです。&lt;br /&gt;
実際の呼び出し方法はこのようになります。&lt;br /&gt;
(StringExtensions を定義した namespace をインポートしてください。)&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
string s = null;
bool isNullOrEmpty = s.IsNullOrEmpty();
&lt;/code&gt;
&lt;/pre&gt;一見、NullReferenceException がスローされそうですが、&lt;br /&gt;
isNullOrEmpty 変数には true が入ります。&lt;br /&gt;
&lt;br /&gt;
今度はよく使用する String.Format(String s, params object[] args) を&lt;br /&gt;
追加してみます。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
public static class StringExtensions
{
    // String の書式項目を、指定した配列内の対応する Object インスタンスの
    // 値と等価のテキストに置換します。
    public static string Format(this String s, params object[] args)
    {
        return String.Format(s, args);
    }
}
&lt;/code&gt;
&lt;/pre&gt;&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
string s = &quot;{0} {1}&quot;.(&quot;A&quot;, &quot;B&quot;);
&lt;/code&gt;
&lt;/pre&gt;変数 s には &quot;A B&quot; が格納されることを期待しましたが、&lt;br /&gt;
実際には、&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;インスタンス参照でメンバ &#39;string.Format(string, object)&#39; に&lt;br /&gt;
アクセスできません。代わりに型名を使用してください。&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
とビルドエラーになってしまいます。&lt;br /&gt;
&lt;br /&gt;
msdn によると、既存のメソッドと同じシグネチャを持つ拡張メソッドを&lt;br /&gt;
定義しても既存のメソッドの方が優先的にバインドされます (拡張メソッドは呼ばれません)。&lt;br /&gt;
&lt;br /&gt;
参考&lt;br /&gt;
&lt;a href=&quot;http://msdn.microsoft.com/ja-jp/library/bb383977.aspx&quot;&gt;http://msdn.microsoft.com/ja-jp/library/bb383977.aspx&lt;br /&gt;
拡張メソッド (C# プログラミング ガイド)&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
つまり、拡張メソッドを追加した型に将来改変が加わり&lt;br /&gt;
同じシグネチャをもつメソッドが定義された瞬間から&lt;br /&gt;
拡張メソッドが呼ばれなくなってしまう危険性があるということになります。&lt;br /&gt;
当然ながら、同じ動きをしない可能性があります。&lt;br /&gt;
&lt;br /&gt;
「ご利用は計画的に。」</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/5213797281648571581/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post_10.html#comment-form' title='1 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/5213797281648571581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/5213797281648571581'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post_10.html' title='拡張メソッド'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-674424187076736230</id><published>2009-09-09T19:22:00.004+09:00</published><updated>2009-09-09T19:28:35.269+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="delegate"/><category scheme="http://www.blogger.com/atom/ns#" term="イベント"/><category scheme="http://www.blogger.com/atom/ns#" term="デリゲート"/><title type='text'>イベントの実装</title><content type='html'>イベントを独自に実装するにはデリゲートを使います。&lt;br /&gt;
注意点は、イベントを発行する前に if (null != MyEvent) { ... } のように&lt;br /&gt;
呼び出し元でイベントハンドラーが追加されていることを&lt;br /&gt;
必ず確認することです。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
public class EventClass
{
    public void DoSomething()
    {
        // イベントハンドラーの登録を確認します。
        if (null != MyEvent)
        {
            MyEvent(this, new MyEventArgs(&quot;Occurred MyEvent&quot;));
        }
    }

    // イベントデリゲート
    public delegate void MyEventHandler(object sender, MyEventArgs e);
    // イベント
    public event MyEventHandler MyEvent;
}

// EventArgs を継承して独自のイベントデータを定義します。
public class MyEventArgs : EventArgs
{
    public MyEventArgs(string myVar)
    {
        this.myVar = myVar;
    }

    public string MyVar
    {
        get { return myVar; }
        set { myVar = value; }
    }

    private string myVar;
}
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
// イベントを受け取る側の実装
EventClass eventClass = new EventClass();
// イベントハンドラーを追加します。
eventClass.MyEvent += delegate(object sender, MyEventArgs e)
{
    MessageBox.Show(e.MyVar);
};

eventClass.DoSomething();
&lt;/code&gt;
&lt;/pre&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMJit6tK_LmVQ63CWwlUWPi7P1pwGT2cwU5VPDoF9wXadPVdtlVnJ4OULDxBhIYSwn9B8cXIol645K9j7X-2bACHsLsrKQFwCaCmnVZhC_GmYyImCVuU4Q-KeRW2CvhKtz57MmYmfP_zg/s1600-h/message.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMJit6tK_LmVQ63CWwlUWPi7P1pwGT2cwU5VPDoF9wXadPVdtlVnJ4OULDxBhIYSwn9B8cXIol645K9j7X-2bACHsLsrKQFwCaCmnVZhC_GmYyImCVuU4Q-KeRW2CvhKtz57MmYmfP_zg/s320/message.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
eventClass.MyEvent に追加したデリゲートが実行され、&lt;br /&gt;
メッセージボックスが表示されます。&lt;br /&gt;
&lt;br /&gt;
ただ、今回のようにイベントの引数が object と EventArgs の派生クラスの&lt;br /&gt;
2 つで構成されるときは&lt;br /&gt;
System.EventHandler&amp;lt;TEventargs&amp;gt; デリゲートを使用し、&lt;br /&gt;
次のように書くこともできます。(1 ステップ減るだけですが)&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
public class EventClass
{
    public void DoSomething()
    {
        if (null != MyEvent)
        {
            MyEvent(this, new MyEventArgs(&quot;Occurred MyEvent&quot;));
        }
    }

    public event EventHandler&amp;lt;MyEventArgs&amp;gt; MyEvent;
}
&lt;/code&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/674424187076736230/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post_09.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/674424187076736230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/674424187076736230'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post_09.html' title='イベントの実装'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMJit6tK_LmVQ63CWwlUWPi7P1pwGT2cwU5VPDoF9wXadPVdtlVnJ4OULDxBhIYSwn9B8cXIol645K9j7X-2bACHsLsrKQFwCaCmnVZhC_GmYyImCVuU4Q-KeRW2CvhKtz57MmYmfP_zg/s72-c/message.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-6539547745444163185</id><published>2009-09-08T16:08:00.001+09:00</published><updated>2009-09-08T16:10:44.568+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="HTTP"/><category scheme="http://www.blogger.com/atom/ns#" term="WebRequest"/><category scheme="http://www.blogger.com/atom/ns#" term="アプリケーション構成ファイル"/><title type='text'>HTTP プロトコル違反</title><content type='html'>WebRequest を利用していると、&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;サーバーによってプロトコル違反が発生しました. Section=ResponseHeader Detail=CR の後には LF を指定しなければなりません。&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
と、WebException がスローされてしまいました。&lt;br /&gt;
ステータスは ServerProtocolViolation となっているので&lt;br /&gt;
HTTP プロトコル違反のようです。&lt;br /&gt;
&lt;br /&gt;
調べたところ、古い CGI では改行を \n で記述されることが多く、&lt;br /&gt;
HTTP サーバーで \r\n に置換するべきところを \n のまま応答を返すので&lt;br /&gt;
厳密な .Net Framework の検証に引っかかっているとのこと。&lt;br /&gt;
&lt;br /&gt;
というわけで、直すべきはサーバー側なのですが、&lt;br /&gt;
自前のサーバーに接続しているわけではなかったので&lt;br /&gt;
曲げて .Net Framework の方に少し馬鹿になってもらい、改行コードが \n でも&lt;br /&gt;
応答を受け入れるよう、アプリケーション構成ファイルに以下を追加。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
  &amp;lt;system.net&amp;gt;
    &amp;lt;settings&amp;gt;
      &amp;lt;httpWebRequest useUnsafeHeaderParsing=&quot;true&quot; /&amp;gt;
    &amp;lt;/settings&amp;gt;
  &amp;lt;/system.net&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
例外を出さず、処理を継続してくれました。</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/6539547745444163185/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/http.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/6539547745444163185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/6539547745444163185'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/http.html' title='HTTP プロトコル違反'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-5627436393817329528</id><published>2009-09-07T15:18:00.009+09:00</published><updated>2009-09-08T10:44:22.487+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="enum"/><category scheme="http://www.blogger.com/atom/ns#" term="where"/><category scheme="http://www.blogger.com/atom/ns#" term="型制約"/><title type='text'>enum を型制約する</title><content type='html'>Generic クラスに enum の型制約をつけたところ、&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
class SomeGeneric&amp;lt;T&amp;gt; where T : &lt;span style=&quot;background-color: #e06666;&quot;&gt;enum&lt;/span&gt;
エラー : 型が必要です。
&lt;/code&gt;&lt;/pre&gt;と、コンパイルエラーが出てしまいます。&lt;br /&gt;
それならと、System.Enum に変更してみました。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
class SomeGeneric&amp;lt;T&amp;gt; where T : &lt;span style=&quot;background-color: #e06666;&quot;&gt;System.Enum&lt;/span&gt;
エラー : 制約は特殊クラス &#39;System.Enum&#39; にはなれません。
&lt;/code&gt;&lt;/pre&gt;これもだめだそうです。そうですか。残念です。&lt;br /&gt;
&lt;br /&gt;
他にも System.Array 型、 System.Delegate 型、 System.ValueType 型で型制約することはできないようです。&lt;br /&gt;
&lt;br /&gt;
参考&lt;br /&gt;
&lt;a href=&quot;http://msdn.microsoft.com/ja-jp/library/56b2hk61.aspx&quot;&gt;http://msdn.microsoft.com/ja-jp/library/56b2hk61.aspx&lt;br /&gt;
コンパイラ エラー CS0702&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
仕方がないので、System.Enum の定義にある IConvertible を型制約にして&lt;br /&gt;
とりあえず int 型にできればいいやという発想。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
&lt;span class=&quot;comment&quot;&gt;// System.Enum の定義&lt;/span&gt;
public abstract class Enum
    : ValueType, IComparable, IFormattable, IConvertible

class SomeGeneric&lt;t&gt; where T : IConvertible
{
    protected T item = default(T);
    
    &lt;span class=&quot;comment&quot;&gt;// enum : long で列挙されると困るので virtual 宣言&lt;/span&gt;
    public virtual T Item
    {
        get
        {
            return item;
        }
        set
        {
            if (item.ToInt32(null) != value.ToInt32(null))
            {
                // Do something
            }
        }
    }
}&lt;/code&gt;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/5627436393817329528/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/enum.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/5627436393817329528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/5627436393817329528'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/enum.html' title='enum を型制約する'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-2370831298556107053</id><published>2009-09-06T15:36:00.004+09:00</published><updated>2009-09-06T21:35:33.192+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="WebBrowser"/><title type='text'>WebBrowser 内のボタンをクリック</title><content type='html'>WebBrowser コントロールを使用していて&lt;br /&gt;
Windows アプリケーションからページ内のボタンをクリックする方法です。&lt;br /&gt;
&lt;br /&gt;
以下のボタンが html で定義されているとして、&lt;br /&gt;
&amp;lt;input type = &quot;button&quot; id = &quot;button1&quot; onclick=&quot;javascript:foo();&quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
HtmlElement element = null;
element = webBrowser1.Document.GetElementById(&quot;button1&quot;);
element.InvokeMember(&quot;click&quot;);
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
javascript の foo() が実行されます。&lt;br /&gt;
type=&quot;submit&quot; でも可。</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/2370831298556107053/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/webbrowser.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/2370831298556107053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/2370831298556107053'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/webbrowser.html' title='WebBrowser 内のボタンをクリック'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2652296181611976813.post-2016830477166630802</id><published>2009-09-05T21:46:00.011+09:00</published><updated>2009-09-06T18:40:08.848+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="デザインパターン"/><title type='text'>ストラテジーパターン</title><content type='html'>I/O が同じで、条件によって異なる処理を行いたい場合や、&lt;br /&gt;
将来的に変更または追加される可能性がある場合、&lt;br /&gt;
switch 文などの条件分岐に処理を埋め込んでいると、&lt;br /&gt;
変更が発生した際に他の条件へ意図しない影響が生じることがあります。&lt;br /&gt;
&lt;br /&gt;
ストラテジーパターンは、インターフェースを介することで&lt;br /&gt;
アルゴリズムを動的に切り替えます。&lt;br /&gt;
&lt;br /&gt;
まずは、ストラテジーパターンを使わない実装。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
static void Main()
{
    string condition = &quot;A&quot;;

    switch (condition)
    {
        case &quot;A&quot;:
            Console.WriteLine(&quot;Executed condition A&quot;);
            break;
        case &quot;B&quot;:
            Console.WriteLine(&quot;Executed condition B&quot;);
            break;
    }
}
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
続いて、ストラテジーパターンを適用した実装。&lt;br /&gt;
&lt;pre class=&quot;src&quot;&gt;&lt;code&gt;
interface IStrategy {
    void Execute();
}

class StrategyA : IStrategy
{
    public void Execute()
    {
        Console.WriteLine(&quot;Called StrategyA.Execute()&quot;);
    }
}

class StrategyB : IStrategy
{
    public void Execute()
    {
        Console.WriteLine(&quot;Called StrategyB.Execute()&quot;);
    }
}

static void Main()
{
    GetStrategy(&quot;A&quot;).Execute();
    GetStrategy(&quot;B&quot;).Execute();
}

IStrategy GetStrategy(string condition)
{
    IStrategy result = null;

    switch (condition)
    {
        case &quot;A&quot;:
            result = new StrategyA();
            break;
        case &quot;B&quot;:
            result = new StrategyB();
            break;
        defalt:
            throw new ApplicationException();
    }

    return result;
}
&lt;/code&gt;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://n2-csharp.blogspot.com/feeds/2016830477166630802/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/2016830477166630802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2652296181611976813/posts/default/2016830477166630802'/><link rel='alternate' type='text/html' href='http://n2-csharp.blogspot.com/2009/09/blog-post.html' title='ストラテジーパターン'/><author><name>くろ</name><uri>http://www.blogger.com/profile/15340228683213286523</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>