例は次のとおりです。
XNamespace ns = "my namespace"
なぜだめですか?:
XNamespace ns = new XNamespace ( "my namespace" )
コンストラクターの代わりに暗黙的/明示的な変換を使用する背後にあるアイデアは何ですか? 快適?
これに関するガイドラインはありますか?
例は次のとおりです。
XNamespace ns = "my namespace"
なぜだめですか?:
XNamespace ns = new XNamespace ( "my namespace" )
コンストラクターの代わりに暗黙的/明示的な変換を使用する背後にあるアイデアは何ですか? 快適?
これに関するガイドラインはありますか?
快適?
多かれ少なかれ、はい。Complex
計算を行う数値のようなオブジェクト (たとえば、 a ) がある場合を考えてみましょう。明らかに、次のようなコードを書きます。
Complex result = c1 * new Complex(2) + new Complex(32);
非常に煩わしく、読みにくいです。ここでは、暗黙的な変換が役立ちます (この例では、代わりに演算子のオーバーロードが使用されますが、同様のオーバーロードが多数発生する可能性があります)。
これに関するガイドラインはありますか?
問題を隠してしまう可能性があるため、暗黙的な変換はできるだけ少なくしてください。暗黙的な変換は、簡潔さを増すのと同じ量だけ明示性を減らします。これは良い場合もありますが、そうでない場合もあります。
上記の例の数値のようなオブジェクトのように、暗黙的な変換を非常に類似した型に制限するのが最善だと思います:int
本質的に is-a Complex
(数学的な観点から; 継承によってモデル化されていなくても)、したがって暗黙的な変換は検出。
VB では、暗黙的な変換は「<code>Widening」と呼ばれます ( とは対照的にNarrowing
、これは ですexplicit
)。
さらに、演算子は本質的にビルダー関数であり、コンストラクターに対するビルダー関数の通常の利点 (の一部) があります。つまり、常に新しいインスタンスを作成する代わりに、キャッシュされた値を再利用できます。
Complex
私の例を考えてみましょう。頻繁に使用される複素数の値をキャッシュしたい場合があります。
Class Complex {
// Rest of implementation.
private static Complex[] cache = new[] {
new Complex(-1), new Complex(0), new Complex(1) };
public implicit operator Complex(int value) {
if (value >= -1 && value <= 1)
return cache[value];
else
return new Complex(value);
}
}
もちろん、このマイクロ最適化が有効かどうかは別問題です。
XName のような単純な型で暗黙的な変換を使用する理由の 1 つは、メソッド呼び出しの利便性だと思います。
たとえば、次のように記述できます。
var info = root.Elements ("user").Element ("info").Value;
データを抽出する際のシンプルさが LINQ のすべてです。
var info = root.Elements (new XName ("user")).Element (new XName ("info")).Value;
最も単純なクエリであっても、LINQ は複雑なクエリに対して十分な価値があるでしょうか?
ここでのもう 1 つの重要な問題は、XName が原子化されていることです。MSDNを参照してください:
XName オブジェクトは原子化されることが保証されています。つまり、2 つの XName オブジェクトがまったく同じ名前空間とまったく同じローカル名を持つ場合、それらは同じインスタンスを共有します。この目的のために、等値演算子と比較演算子も明示的に提供されています。
他の利点の中でも、この機能によりクエリの実行が高速化されます。要素または属性の名前でフィルタリングする場合、述語で表現された比較では、値の比較ではなく、ID の比較が使用されます。2 つの文字列を比較するよりも、2 つの参照が実際に同じオブジェクトを参照していることを確認する方がはるかに高速です。
コンストラクターで原子化を提供することはできませんが、変換を定義すると、対応するオブジェクトをプールから選択して、新しいインスタンスであるかのように返すことができます。
暗黙的/明示的な変換の使用は利便性の問題であり、多くのプログラミング ガイドラインでは、明示的なConvertToXXX
メソッドを優先して避けることを推奨しています。
問題の 1 つは、暗黙的/明示的な変換を使用すると、キャスト演算子の関数がさらにオーバーロードされることです。それはそれに二重の目的を与えます
残念ながら、C# は既に他の領域で後者を行っています (プリミティブとボクシングを使用)。
2つのクラスを相互に変換できる必要があるが、この動作を自動的に許可する基本クラスのインターフェイスを共有していない場合は、変換を使用します。暗黙の変換でデータが失われる可能性はありません。多くの場合、「拡大」コンバージョンと見なされます。たとえば、int
aからaへのlong
変換は拡張変換であり、暗黙的な変換に固有の問題はありません。明示的な変換には、データ損失の可能性が含まれる場合があります。aは、その値に応じて、にlong
変換できる場合とできない場合があります。int
暗黙の変換で使用したトリックの1つは、別の合理的なオプションがない場合に、異なる名前空間のクラスを相互に変換することです。たとえば、あるWCFサービスは、別の名前空間のWCFサービスに渡す必要のあるAuthenticationTokenオブジェクトを返します。どちらにもこのAuthenticationTokenオブジェクトがあり、継続的な変換は面倒でした。私のソリューションpublic static implicit operator
では、部分的なクラスを使用して、各方法で変換する機能を追加しました。
個人的には、rhs がクラスの静的メンバーに変換される可能性があることがわかっている場合に変換を使用します (color = "red"
暗黙的に言うようにcolor = Colors.Red
)
実際に新しいインスタンスを作成する場合は、new 演算子を使用します。