2010年07月21日

StringCollection を string[] に変換

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

たぶん、ほとんど使われなくなったと思われる StringCollection クラスですが、 Visual Studio のプロジェクトの Properties フォルダにあるSettings.settings で設定した文字列リストは、StringCollection 型になっています。

これを stringの配列にしたいときのC#のコードです。


Enumerable.Cast メソッドで IEnumerableに型変換してあげれば、 LINQでおなじみの ToAray()メソッドで、string[] に変換できます。

C#2.0のときは、StringCollection.CopyToを使ったりしてましたが、Cast使うほうが直感的に 書けます。

  

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

2007年09月04日

C#3.0:fromや selectは[キーワード]という位置づけなのでしょうか?

   このエントリーをはてなブックマークに追加 Clip to Evernote
fromや selectは[キーワード]という位置づけなのでしょうか?

当然、C#2.0では、from、selectは[キーワード]じゃないから、
int from;

といった変数を使っているコードを
C#3.0でコンパイルしたときには、エラーにはなってほしくない。
実際、エラーにはならない。

だから、
 int from = 10;  // 変数の from
Console.WriteLine(from.ToString());
var list = from c in objs
where c.Name == "XXX"
select c.Name;

というコードが書ける。
LINQとしての selectなのかそうではないのか、文脈をみて判断することになる。コンパイラを作る側も大変だろうけど、エディタ側も大変そう。

さすがに、以下のコードはエラーになるみたい。

    int[] select = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

var numsPlusOne =
from n in select
select n + 1;

まあ、こんなコード書く人いないだろうから、エラーになっても問題はないけどね。

「C# Language Specification Version 3.0」を見てみたけど、fromや selectは[キーワード]じゃなかった。


このことに気がついた時に、Delphi(Object Pascal)のときも同じことがあったなーって、思い出した。
Delphiでは、for や if は予約語でしたけど、abstract, virtual, readonly とかは予約語じゃなくて、別の指令語(正確な名前は忘れた)とかいう分類だったと思う。
integerというのも予約語じゃない。
なので、
   var
integer:double; // integerという名前の Double型の変数

なんていうわけわかんない変数宣言ができた。
コンパイラー屋さんも、過去との完全互換を取るためにいろんな苦労をしてるんだなー。  
Posted by gushwell at 21:23Comments(2)TrackBack(0)

2007年08月17日

C#3.0:ラムダ式

   このエントリーをはてなブックマークに追加 Clip to Evernote
ラムダ式

delegate int MyFunction(int i);

static int Triple(int n) {
return n * 3;
}

static void Test() {
// C#1.1
MyFunction f = new MyFunction(Triple);
int n = f(11);
Console.WriteLine(n);
}

このコードは、delegateの動きを説明した C#1.1のコード。

これが、C#2.0になると、こんな書き方になる。

delegate int MyFunction(int i);

static void Test() {
// C#2.0 匿名メソッド
MyFunction f3 = delegate(int x) { return x * 3; };
n = f3(20);
Console.WriteLine(n);
}

わざわざ Tripleというメソッドを定義する必要がなくなったわけだ。

そして、C#3.0では、

delegate int MyFunction(int i);

static void Ramda() {
// C#3.0 ラムダ式
MyFunction f4 = (int x) => { return x * 3; }; // (*)
n = f4(30);
Console.WriteLine(n);
}

ここまでは、C#2.0 と C#3.0 では、記述方法が変化しただけと見ることもできる。
さらに、

    MyFunction f4 = (int x) => return x * 3;    // (*)

と書ける。さらに、この(*)の記述が、

    MyFunction f4 = (int x) => x * 3;

    MyFunction f4 = (x) => x * 3;

    MyFunction f4 = x => x * 3;

と短くすることができる。

いきなり、最後の文を見せられたときは、いきなり出てきた xって何だ?
と面食らったけど、順番に見ていけば、それほど難しくはない。
でも、慣れるのが大変そう。
  
Posted by gushwell at 20:54Comments(0)TrackBack(2)

2007年08月16日

C#3.0:拡張メソッド

   このエントリーをはてなブックマークに追加 Clip to Evernote
C#3.0:拡張メソッド

例えば、単語の先頭を大文字に変換する ToTitleCaseメソッドを作成したいという要求があったとします。
そういう場合は、StringUtilsとかいうクラスを作成し、そこに、staticメソッドを用意するのが、一般的でした。
しかし、System.Stringクラスに追加できれば、もっと使い勝手が良くなります。C#3.0では、拡張メソッドを使うことで、
string s = "microsoft";
Console.WriteLine(s.ToTitleCase());

という記述が可能になります。
ToTitleCase 側は、以下のようなコードになります。

static class StringExtensions {
public static string ToTitleCase(this string s) {
var cultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture;
var textInfo = cultureInfo.TextInfo;
return s = textInfo.ToTitleCase(s);
}
}

拡張メソッドにするには、staticメソッドにすること、最初の引数は、this指定することが必要です。
ようは、コンパイラが、
Console.WriteLine(s.ToTitleCase());

というコードを
Console.WriteLine(StringExtensions.ToTitleCase(s));

に置き換えてくれるわけですね。

もちろん、引数を取るメソッドやジェネリックメソッドを拡張メソッドとして定義することもできます。

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