usingキーワード
usingキーワードについては.NET入門コラムの以前の記事で特集を組みました。これは別に新しい機能でありませんが、それでもここで触れる価値はあり、少なくとも同記事を紹介する意味はあるように思われます。usingキーワードの主な長所は、try ... finally動作の実装に使用でき、破棄可能な型の自動クリーンアップを実現できることです。これは例えば、データ読み込みを行うDataReaderのようなオブジェクトで処理終了時にコネクションが確実に破棄されるような動作を実現したい場合に必要な機能で、このような機能を実装するときにはusingキーワードが大いに役立ちます。
using (IDataReader reader = provider.ExecuteReader(dataCmd))
{
// ...
}
ローカル型推論
ローカル型推論についても以前.NET入門コラムの別の記事で扱いましたが、やはりここで触れる価値はあるでしょう。確実に理解すれば何かと役に立つからです。varキーワードを用いて変数を定義すると、コンパイル時に型が自動的に決定され、その型に置き換えられます。これは次に示すようなクエリ式で役に立ちます。見たところuntypedのようでもあり、variant型のような印象すら与えますが、実際は違います。これはコンパイル時に型が設定される、強く型付けされたオブジェクトです。
var i = 5;
int i = 5;
string[] words = { "cherry", "apple", "blueberry" };
var sortedWords =
from w in words
orderby w
select w;
オブジェクト初期化子とコレクション初期化子
初期化子とはオブジェクトの生成と初期化をワンステップで行うための簡略構文です。次の例の1行目のように、パラメータのないコンストラクタでは括弧を省くこともできます。
Point p = new Point { X=3, Y=99 };
Student myStudent = new Student() {
Name = "John Doe",
Class = "Senior",
School = "Carmel" };
この機能は、オブジェクトのコレクションを生成してLINQクエリのような操作を実行してみせるのには向いています。しかし、大量のデータセットを初期化する場合には現実を直視し、そのような情報をデータベースではなくコードに格納することが果たして適切かどうか十分検討することをお勧めします。
初期化子はコンストラクタで使うと非常に効果的です。次に示すインスタンスでは、パラメータ付きのコンストラクタを呼び出す際に残りのプロパティを初期化しています。このコンストラクタはこれらのパラメータをすべて受け取るのが通例なので模範的な構成とは言えませんが、要点をよく示しています。
class Customer
{
public Customer(string customerKey) { ... }
public string CustomerKey { get { ... } }
public string ContactName { get; set; }
public string City { get; set; }
}
var c = new Customer("MARKS"){
ContactName = "Mark Strawmyer",
City = "Indianapolis"
}
拡張メソッド
拡張メソッドを使うと既存の型に新しい機能を作成できます。型が封印(sealed)されていても構いません。拡張メソッドは、静的メソッドのように宣言し、インスタンスメソッドのように呼び出します。インターフェースまたは生成型でも使用できます。次の例では、拡張メソッドを用いてdecimal型にTripleメソッドとHalfメソッドを追加しています。
static class ExtensionSample
{
public static decimal Triple( this decimal d ) { return d*3; }
public static decimal Half( this decimal d ) { return d / 2; }
}
decimal y = 14M;
y = y.Triple().Half();
拡張メソッドは非常に強力なツールとなり得ますが、注意して使わないと非常に悩ましいツールにもなり得ます。同じコードベースで作業する他の開発者が拡張メソッドを使うかどうか自由に決められるように、名前空間を独立させることを検討してください。オブジェクトクラスを拡張してすべてのオブジェクトに拡張メソッドを置きたくなる気持ちを抑えることが重要です。また、一貫性を保つために、一般のインスタンスメソッドと同じように動作させることも重要です。
次に示すコードは、拡張メソッドの形式として避けるべき、非常に悪い例です。名前空間はSystemで、これは拡張メソッドの有効範囲が、それと接触することになるすべてのコードに及ぶことを意味します。このコードは、すべてのオブジェクトを拡張します。また、通常のインスタンスメソッドのようには動作しません。通常、nullオブジェクトに対してインスタンスメソッドを呼び出した場合は、NullReferenceExceptionが返され、Booleanのtrueまたはfalseが返されることはありません。この例のようなコードを使用することはお勧めしません。
namespace System
{
public static class MyExtensions
{
public static bool IsNull(this object o) {
return o == null;
}
}
}
while (!myObject.IsNull()) { ... }
LINQを高速化する工夫
ここでLINQについて多くを語るつもりはありません。それだけで、いくつも記事が書けるほどの内容があるからです。あるプロジェクトで実際に経験したLINQを高速化する工夫を紹介します。まずTable.ToList().Find()を使用すべきかどうか、慎重に検討することが重要です。普通はTable.Where()を使用した方がよいでしょう。ToList().Find()はテーブルのすべてのレコードを返し、その後、メモリ内でフィルタを実行します。一方、Table.Where()はSQL内で実行され、要求した行だけを返します。
もう1つの工夫は、LINQPadという名前で知られているツールを利用することです。このツールを使うと、LINQでデータベースに対して対話的なクエリを実行できます。これはC#の任意の式やステートメントブロックを実行するコードスニペット統合開発環境(IDE)であり、LINQを実際に試すとき非常に役立ちます。
