2008年01月30日

C#3.0:オブジェクト初期化しを使うべし

   このエントリーをはてなブックマークに追加 Clip to Evernote
ブログ「当面C#と.NETな記録」の記事『■[C#] オブジェクト初期化子とコレクション初期化子』の「オブジェクト初期化子とコレクション初期化子が LINQ を支える影の大黒柱だったんですね。」

という言葉に触発されて、C#でちょっとしたLINQのコードを書いてみた。

var db = new NorthwindDataContext();
db.Log = Console.Out;
var query = from e in db.Employees
select new SampleEmp {
Name = e.FirstName + " " + e.LastName,
Age = DateTime.Today.Year - e.BirthDate.Value.Year
};
foreach (var e in query) {
Console.WriteLine("{0} {1}", e.Name, e.Age);
}


以下は、まったく同じことをやるのに、クラスのコンストラクタを使っている。

var db = new NorthwindDataContext();
db.Log = Console.Out;
var query = from e in db.Employees
select new SampleEmp(
e.FirstName + " " + e.LastName,
DateTime.Today.Year - e.BirthDate.Value.Year
);
foreach (var e in query) {
Console.WriteLine("{0} {1}", e.Name, e.Age);
}


なお、SampleEmpクラスは、以下のようなクラス。

class SampleEmp {
public SampleEmp(string name, int age) {
Name = name;
Age = age;
}
public SampleEmp() { }
public string Name { get; set; }
public int Age { get; set; }
}


結果は2つとも同じだし、発行されるSQLも同じ。

しかし、次のコードはどうなるのか?

var db = new NorthwindDataContext();
db.Log = Console.Out;
var query = from e in db.Employees
select new SampleEmp {
Name = e.FirstName + " " + e.LastName,
Age = DateTime.Today.Year - e.BirthDate.Value.Year
} into t
orderby t.Name
select t;
foreach (var e in query) {
Console.WriteLine("{0} {1}", e.Name, e.Age);
}


このSQLは、

SELECT [t1].[value] AS [Name], [t1].[value2] AS [Age]
FROM (
SELECT ([t0].[FirstName] + @p0) + [t0].[LastName] AS [value],
@p1 - DATEPART(Year, [t0].[BirthDate]) AS [value2]
FROM [dbo].[Employees] AS [t0]
) AS [t1]
ORDER BY [t1].[value]


だ。ほー、良くできていますね。DATEPARTなんて関数があったんだ。

では、コンストラクタを使った場合は、どうなるのでしょうか?

var db = new NorthwindDataContext();
db.Log = Console.Out;
var query = from e in db.Employees
select new SampleEmp(
e.FirstName + " " + e.LastName,
DateTime.Today.Year - e.BirthDate.Value.Year
) into t
orderby t.Name
select t;
foreach (var e in query) {
Console.WriteLine("{0} {1}", e.Name, e.Age);
}


無事、コンパイルできました。
しかし、実行してみると、以下の例外が発生してしまいます。

System.NotSupportedException はハンドルされませんでした。
Message="メンバ 'Gushwell.SampleEmp.Name' には、サポートされる SQL への変換
がありません。"


つまり、コンストラクタを使ってしまうと、コンストラクタの中で何が起きているかが分からないので、orderby t.Name の Nameプロパティが、その前のクエリとどう関連しているのかが理解できず、SQL文にすることが出来ないわけです。

そういう意味からも、LINQ + C#では、「オブジェクト初期化しを使うべし」が当てはまることになりますね。

  

Posted by gushwell at 21:57Comments(2)TrackBack(0)

2008年01月29日

Linq to XML その9

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

PI(Processing Instructions)を追加するコードを書いてみた。
これもとても簡単だ。

XDocument xdoc2 = XDocument.Load("people.xml");
XProcessingInstruction xpi = new XProcessingInstruction("xml-stylesheet",
"type='text/xsl' href='sample.xsl'");
xdoc2.Root.AddFirst(xpi);


AddFirstメソッドを使うところが、今までと違う部分。
  
Posted by gushwell at 21:16Comments(1)TrackBack(0)

2008年01月23日

「C#プログラミングレッスン」 Debug,Trace編

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

Debug, Traceクラス関連の説明をしています。カスタムリスナーの作成や構成ファイルの記述についても書いています。
なお、.NET Framework2.0で追加された TraceSourceクラスについては、かなり詳しく説明しています。
  
Posted by gushwell at 22:05Comments(0)TrackBack(0)

Linq to XML その8

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

XMLファイルの中に、

  <Person>
<Name>高杉晋作</Name>
<Age>21</Age>
</Person>


という要素があったとします。
今までと違うのは、IsReal属性がない点です。
この要素があるXMLファイルを処理すると、今までのプログラム(以下)だと例外が発生してしまいました。

XDocument xdoc = XDocument.Load("people.xml");
foreach (var xperson in xdoc.Root.Elements()) {
bool isReal = (bool)xperson.Attribute("IsReal"); //★
if (isReal) {
XElement xname = xperson.Element("Name");
XElement xage = xperson.Element("Age");
Console.WriteLine(xname.Value + ":" + xage.Value + "歳");
}
}


で、このプログラムを改良してみました。
IsReal属性がない場合、 trueが指定されているものとして処理を継続することにします。

★の行を以下のように書き換えるだけです。

bool isReal = (bool?)xperson.Attribute("IsReal") ?? true;


?? は null合体演算子といって、値が null だった場合に、??に続く値を利用するという指定です。もちろん、nullableタイプのみに利用できます。

この場合は、xperson.Attribute("IsReal") を (bool?) nullを許容する bool型にキャストし、その結果が nullだったら(つまり、IsReal属性がなかったら)、trueとして評価することになります。

クエリ式を使った場合も同様です。

XDocument xdoc = XDocument.Load("people.xml");
var query = from xperson in xdoc.Root.Elements()
where (bool?)xperson.Attribute("IsReal") ?? true == true
select new {
Name = xperson.Element("Name").Value,
Age = (int)xperson.Element("Age")
};
foreach (var p in query)
Console.WriteLine(p.Name + ":" + p.Age + "歳");


nullableってC#2.0のときには、なかなか使う場面がなかったけど、C#3.0になって俄然その存在感が増したように思います。

  
Posted by gushwell at 21:01Comments(1)TrackBack(0)

2008年01月22日

.NET Framework ライブラリ ソース コード

   このエントリーをはてなブックマークに追加 Clip to Evernote
.NET Framework ライブラリ ソース コードが利用可能になったということで、遅れば
せながら僕もここ「Configuring Visual Studio to Debug .NET Framework Source Code」を参考にしてセットアップしようとしたら、

---------------
このソフトウェア更新の対象製品はこのコンピュータにインストールされていません。
[キャンセル] をクリックして、セットアップを終了してください。
---------------

というメッセージが出て、Hotfixのアップデートでつまずいてしまいました。

Webで検索したら、
ひろえむの日々是勉強」のページに対応策が書いてありました。
助かりました (^ ^/

Fotfixのアップデートをしなくても、上記ページの手順に従い、オプションの設定をしたら、出来ました。
じゃあ、FotFixは何??? という疑問は残りますが...

ちなみに、VS2008のオプション画面の設定のsymbol file location には
https://Referencesource.microsoft.com/symbols
を設定します。

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

2008年01月17日

Linq to XML その7

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

架空の人物だけを取得し、

<?xml version="1.0" encoding="utf-8"?>
<People>
<Person Age="40">
<Name>明智小五郎</Name>
</Person>
<Person Age="41">
<Name>両津勘吉</Name>
</Person>
</People>


というXMLファイルを作成してみようと思います。
読み込むXMLと異なるスキーマで出力していることに注目です。
ついでに、年齢に1を加える処理も追加してみました。

XDocument xdoc = XDocument.Load("newpeople.xml");
var query = from xperson in xdoc.Root.Elements()
where (bool)xperson.Attribute("IsReal") == false
select new XElement(
        "Person",
new XAttribute("Age", (int)xperson.Element("Age") + 1),
new XElement(xperson.Element("Name"))
);
XElement x = new XElement("People", query);  //★
x.Save("notreal.xml");


クエリ式で、架空の人物だけを抜き出すのですが、その際に返す型を XElement型にしています。
こうすることで、★の行のように、XElementのコンストラクタの第2引数に渡すことができます。

どうです。たったこれだけのコードで実現できるって、ちょっと感動ものじゃないですか?
これを DOMで書くとかなり面倒だと思う。
  
Posted by gushwell at 21:27Comments(1)TrackBack(0)

2008年01月13日

「C#プログラミングレッスン」 ファイル・フォルダ編

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

Stream関連の各種クラスの説明のほかに、FIle, FileInfo, Directory, DirectoryInfo, BinaryReader, BinaryWriter, GZipStream, Encodingクラスについて説明しています。

また、ファイルフォルダとは直接関係ありませんが、構成ファイル、バージョン情報、シリアライズについても説明しています。
  
Posted by gushwell at 18:14Comments(6)TrackBack(0)

2008年01月11日

Internet Explorer ではこのページは表示できません

   このエントリーをはてなブックマークに追加 Clip to Evernote
仕事で使ったいる Vistaマシンで、突然、

Internet Explorer ではこのページは表示できません 

可能性のある原因:
インターネットに接続されていない。
Web サイトに問題が発生している。
アドレスに入力の間違いがある可能性がある。


といった表示がでて、インターネットに接続できなくなってしまいました。

Internet Explorer 7 でエラー メッセージ "Internet Explorer ではこのページは表示できません" が表示される
http://support.microsoft.com/kb/926431/ja

Vistaで「Internet Explorer ではこのページは表示できません」
http://hongopc.exblog.jp/6441784/

Internet Explorer ではこのページは表示できません
http://pcproblem.at.webry.info/200712/article_34.html

などを参考にしながら、復旧を試みるも、すべてダメ。
まったく原因が分かりません。
今日の朝、windows updateを実行し、昨年末から溜まっていた更新プログラムをインストールしたからでしょうか?

ちなみに、メールは問題なく送受信できるし、イントラネットのサイトも問題なくアクセスできます。
不可解なのは、同じPCに入っている Sleipnirというブラウザだと問題なく表示できることです。もちろん、IEのインターネットオプションで接続しています。
いったい、どうなってるのでしょうか?

もうやれることはすべてやったという感じで、疲れ果てたのであきらめました。
数日前の環境に戻すという選択肢もあるのですが、それも面倒なので、Sleipnirを使い続けることにします。
  
Posted by gushwell at 21:21Comments(0)TrackBack(0)