2008年10月31日

LINQ to XMLのハロウィーン問題

   このエントリーをはてなブックマークに追加 Clip to Evernote
宣言型コードと命令型コードの混在のバグ (C#) (LINQ to XML)
に、「ハロウィーン問題」と呼ばれる問題が載っている。

XMLの要素を反復処理するコードを LINQ を使用して記述する場合、
そのループ処理の中で、要素の追加や削除を行うと、意図どおりに動作しないというもの。

あれ、これって、通常のコレクションでも同じ問題があるんじゃないの。
と思って、以下のようなコードを書いてみた。

 var list = new List {
1,2,3,4,5,6,7
};
foreach (var i in list) {
list.Add(i);
}

これを実行してみたら、なんと、

「{System.Collections.ListDictionaryInternal}コレクションが変更されました。列挙操作は実行されない可能性があります。」

という例外が出る。
へー、そんなチェックをしていたんだ。普段こんなコードを書いたことが無いので、初めて知りました。
LINQ to XMLだと、例外が出ないんですね。

  

Posted by gushwell at 20:50Comments(2)TrackBack(0)

2008年10月29日

「LINQ to XML 軸」?

   このエントリーをはてなブックマークに追加 Clip to Evernote
LINQ to XML 軸

「軸」ってなんですか?
日本語としてものすごく違和感がある。
LINQ to XML Axesの略らしい。
調べたら、Axes は、 Axisの複数形。
確かに、しっくりくる訳をつけるのは難しいのかな。
でも、なんだかなー。
  
Posted by gushwell at 20:38Comments(0)TrackBack(0)

2008年10月28日

昔書いた備忘録(3)

   このエントリーをはてなブックマークに追加 Clip to Evernote
2002年当時に書いた備忘録の第3弾

-------------------------------------

スローする例外の型
Exception, ApplicationException, SystemException, ArgumentException など、他の例外の基底になっている例外クラスをスローしてはいけない。あまりにもあやふや過ぎる。

is-a 関係か、can-do関係か
is-a 関係ならば、クラス継承を can-do 関係ならば、interface を!

配列の参照を返すメソッド
要素がひとつもない配列を返す必要がある場合、null を返すこともできるが、長さゼロの配列を返すようにしたほうが良い。そのほうが、呼び出し側のコードがすっきりする。

Array.Copy
配列のコピー(Array.Copy メソッド)は、簡易コピーを行うので、配列の要素が参照型であれば、新しい配列も既存のオブジェクトを参照していることに注意。

ビットフラグ
ビットフラグとして利用する列挙型を定義するときは、1つ1つの識別名に対して個々の数値を明示的に設定しなければならばい。また定義した列挙型には、System.FlagsAttribute属性を適用する必要がある。
なお、C# では、System.FlagsAttribute は、Flags と省略できる。

[Flags]
public enum Action {
 Read  = 0x001,
 Write = 0x002,
 Delete = 0x004,
 Query = 0x008,
 Sync  = 0x0010
}

文字列を引数に持つメソッド
通常、StringBuilder をメソッドの引数にすることはない、通常は、String を引数にとるようにする。


Enumの識別名と数値
Enum.GetValuesメソッドを使うことで、識別子の一覧を得られる。このメソッドと、ToString メソッド(および、int へのキャスト)を使えば、値と識別名の一覧が分かる。
  
Posted by gushwell at 21:13Comments(0)TrackBack(0)

2008年10月24日

昔書いた備忘録(2)

   このエントリーをはてなブックマークに追加 Clip to Evernote
パス名の指定 文字列リテラルの指定
パス名文字列リテラルをあらわすには、2つの方法がある。

string path = "C:\\Windows\\System32\\Notepad.exe";
string path = @"C:\Windows\System32\Notepad.exe";

@を先頭に置くと、\記号をエスケープ記号ではなく、\そのものと解釈するので、読みやすくなる。
@リテラル文字列を使用すると、パス名などの表記がすっきり!。

文字列の連結
文字列の連結は、+ 演算子で可能だが、リテラルでない文字列を連結する場合には、System.Text.StringBuilder型を利用したほうが良い。+ 演算子をリテラルでない文字列に適用すると、多くの文字列オブジェクトがガベージコレクションの対象となるため、速度的に不利になる。

イベント
イベント情報を保持する型は、System.EventArgs型から派生するのが慣例になっている。
型の名前は、EventArgsで終わるようにする。

イベントハンドラの名前は、EventHandlerで終わるのが慣例になっている。また、戻り値は、void で、引数は2つとる。最初の引数は、Object 型で、通知を送信したオブジェクト、第2引数は、EventArgs から派生した型で、土の受信者が必要とする追加情報とする。

※ 引数の慣習は、Delphi と考え方は同じですね。

インデクサ
Object を引数として指定し、連想配列の値を検索するインデクサを作成することは、かなり一般的に行われている。System.Collections.Hashtable 型には、キー(Object)をとって、そのキーに関連づけされた値(Object型)を返すインデクサが定義されている。
また、インデクサのオーバーロードも可能。

可変個の引数
メソッドの最後の引数だけに、params キーワードをつけることができる。
このパラメータは、型は何でもかまわないが、1次元配列である必要がある。
任意の型を受け取れるようにするには、Object[] をとるようにする。

追記
2008/10/25 渋木さんの指摘により文字列リテラルの表現を訂正。
  
Posted by gushwell at 22:26Comments(4)TrackBack(0)

2008年10月23日

「The power of closures in C# 2.0」をC#3.0に

   このエントリーをはてなブックマークに追加 Clip to Evernote
The power of closures in C# 2.0にあるコードをC#3.0で書き換えてみた。

// コード1
public IEnumerable<Employee> Managers(IEnumerable<Employee> emps) {
    return emps.Where(e => e.IsManager);
}

// コード2
public IEnumerable<Employee> HighPaid(IEnumerable<Employee> emps) {
    int threshold = 150;
    return emps.Where(e => e.Salary > threshold);
}

// コード3
public Predicate<Employee> PaidMore(int amount) {
    return (e => e.Salary > amount);
}

private void Hoge() {
    // 確認のためのコード
    var emps = new List<Employee> {
        new Employee { Name = "John", IsManager = true, Salary = 200, },
        new Employee { Name = "Mike", IsManager = false, Salary = 170, },
        new Employee { Name = "Joe", IsManager = false, Salary = 140, },
    };

    Managers(emps).ToList().ForEach(Console.WriteLine);
    Console.WriteLine();
    HighPaid(emps).ToList().ForEach(Console.WriteLine);
    Console.WriteLine();

    // コード4
    Predicate<Employee> highPaid = PaidMore(150);
    Console.WriteLine(highPaid(emps[0]));
}


// 確認のためのEmployeeクラス
class Employee {
    public bool IsManager { get; set; }
    public int Salary { get; set; }
    public string Name { get; set; }
    public override string ToString() {
        return string.Format("{0} {1} {2}", Name, IsManager, Salary);
    }
}



どちらかと言うと、上記ページに書いてあるrubyの方に似てますね。   
Posted by gushwell at 21:55Comments(0)TrackBack(1)

2008年10月22日

昔書いた備忘録(1)

   このエントリーをはてなブックマークに追加 Clip to Evernote
このところ、ここに書く話題がないです。

C#を覚え始めたころ(2002年の秋ころ)に書いたC#の備忘録が出てきたのでアップしてみます。

------
ICloneable
そのクラスが複製可能な場合には、ICloneableインターフェースを実装しておいたほうが良い。

定数か読み取り専用フィールドか
定数が他のモジュールでも利用される場合は、その定数を利用するすべてのモジュールを再構築しなければならない。
このため、他のモジュールから参照され、かつ変更の可能性があるのならば、定数ではなく、読み取り専用フィールドを使ったほうが良い。

フィールドの初期化
フィールドをインラインで初期化する構文は、コンストラクタで値を設定するコードと同じ意味になる。

is演算子
is演算子は決して例外をスローしない。
オブジェクト参照が、nullの場合や、互換性の無い型の場合は、falseを返す。

usingディレクティブ
using GSample = Gushwell.Library.Sample
とすれば、
 obj = new GSample();
と、フルネームを使わずに、オブジェクトをnewできる。
※ Sample はクラス名

値型の設計の指針
単純型のような動作をする。
ほかの型から継承する必要がない。
ほかの型の基底型にはならない。
サイズが比較的小さい

  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2008年10月20日

IME 2007 変換精度、学習機能を改善した修正プログラム

   このエントリーをはてなブックマークに追加 Clip to Evernote
IME 2007 変換精度、学習機能を改善した修正プログラム」が公開されてますね。
IME2007は、時々学習を無視した変な変換をしてたのですが、これが解消されるかな。


  
Posted by gushwell at 21:00Comments(0)TrackBack(0)

2008年10月19日

「C#プログラミングレッスン」 LINQ to Object編

   このエントリーをはてなブックマークに追加 Clip to Evernote
Gushwell's C# Programing Page --「窓際プログラマーの独り言」別館で、メールマガジン『C#プログラミングレッスン』のバックナンバー「LINQ to Object文法編」をダウンロードできるようにしました。

今、次の連載について検討中です。
候補としては、
・LINQ to XML
・リフレクション
・クラス設計
といったところです。
来月くらいから、メルマガの発行を再開できればと思っています。

LINQ to SQL , Silverlightという要望もあったのですが、テキストだけでの解説が難しいため、見送ることにしました。
Silverlightについては僕自身が良く分かっていないというのも大きいですが...



  
Posted by gushwell at 20:55Comments(0)TrackBack(0)