2013年4月11日木曜日

『なんでこれコンパイル通るんだっけ?』

あらかじめ言っておくと、この話にオチはありません。なんかすいません。

深く考えもせず、こんな感じのコードを書いていました。

public void SetValidChars(CharType type, string option)
{
  var validChars = new List<char>();

  if (type == CharType.AllAscii)
    validChars.AddRange(Enumerable.Range(0x20, 0x7f - 0x20)
                                  .Select(n => Convert.ToChar(n)));
  else if (type == CharType.NumericOnly)
    validChars.AddRange("0123456789");
  else if (type == CharType.Optional)
    validChars.AddRange(option);

  // この後、validCharsを使ってごにょごにょ
}

コンパイルかけて、UTも通して、さてと、とコードを眺めていたら、文字を眺めていてゲシュタルト崩壊起こしたときのように、なんだか急に不安になってきて、『…なんでこのコードコンパイル通るんだっけ?』。なんでList<char>.AddRange()にstringを引き渡せるんだっけ?

念のため「List<T>.AddRange」のオーバーロードを確認してみようとググってみたら、パラメータに「IEnumerable<T>」を受け付けるモノのみ。ふーん。やっぱそうだよね。

じゃあ、stringクラスのほうで「IEnumerable<char>」への暗黙の変換とかができるのかな?と思い、まずはstringクラスの型の構文をググって調べてみた。



ふーん。「IEnumerable」と「IEnumerable<string>」なのか。それだと「IEnumerable<char>」には勝手に変換できないよな。じゃあ、stringクラスに「IEnumerable<char>」に暗黙的に変換できるImplicitなオペレータがあるんだろう。と思って探してみたけど、…ない。…うん。そんなの見た覚えない。

もうわからん。なんか僕が知らない型変換の仕組みでもあるのか?と軽くパニックになりかけたところで、

『ん?stringクラスがIEnumerable<string>を実装?』。いったい何を列挙すんだよ、それ?

よくよくググった結果を見てみると、「.net Framework 2.0」と書いてある。まさかなー。と思いながら「.net Framework 4.5」に切り替えてみると、

public sealed class String : IComparable, 
 ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, 
 IEnumerable, IEquatable<string>

わぁ。やっぱり「IEnumerable<char>」じゃねーか。じゃぁ、「2.0」バージョンでの説明が間違ってたんだよね。と、ちょっとほっとした。

…一応フィードバックを書いといたよ。

0 件のコメント:

コメントを投稿