4

私は、さまざまな測定単位 (メートル、フィート、インチなど) を表す構造体の名前空間を持っています...合計で 12 個あり、T4 テンプレートの厚意により生成されました :) 。

各構造体には、値を他の測定値型にキャストすることをサポートする暗黙のキャスト演算子が含まれているため、次の構文は有効です。

var oneThousandMeters = new Meters(1000);    
Kilometers aKilo = oneThousandMeters ;     // implicit cast OK. Value = 1 Km

さらに嬉しいことに、任意の測定単位を保持できるDistanceという包括的なクラスがあり、測定値との間で暗黙的にキャストすることもできます...

var magnum = new Distance(12, DistanceUnits.Inches); 
Feet wifesDelight = magnum;               // implicit cast OK. Value = 1 foot.

.NET フレームワーク標準に​​従って、すべての文字列の書式設定と解析は、ICustomFormatter を実装する外部の FormatProvider によって処理されます。残念なことに、これは値が Format メソッドに渡されるときにボックス化されることを意味し、Format メソッドは、オブジェクトに作用する前に、すべての既知の測定タイプに対してオブジェクトをテストする必要があります。内部的には、Format メソッドはとにかく測定値を Distance 値にキャストするだけなので、ここで質問が来ます....

質問:

public string Format(string format, object arg, IFormatProvider formatProvider)
{
    Distance distance;           

    // The following line is desired, but fails if arg != typeof(Distance)   
    distance = (Distance)arg;    

    // But the following tedious code works:
    if(arg is Distance)
       distance = (Distance)arg;
    else if(arg is Meters)
       distance = (Distance)(Meters)arg;     // OK. compile uses implicit cast. 
    else if(arg is Feet)
       distance = (Distance)(Feet)arg;       // OK. compile uses implicit cast. 
    else if(arg is Inches)
       distance = (Distance)(Inches)arg;     // OK. compile uses implicit cast. 
    else
        ... // tear you hair out for all 12 measurement types
}

これに対する解決策はありますか、それとも値型の解決できない欠点の 1 つにすぎませんか?

PS:この投稿を確認しました。質問は似ていますが、探しているものではありません。

4

2 に答える 2

5

それは、ボックス化解除の変換をユーザー定義の変換から分離することの問題です。両方が発生する必要があります-ボックス化を解除するタイプを指定するだけでなく、ユーザー定義の変換が必要な場合にコンパイラに知らせる必要があります。動的型付けを使用していない限り、コンパイル時にユーザー定義の変換を選択する必要があるため、コンパイラは変換元の型を知る必要があります。

1 つのオプションは、すべての構造体が実装するIDistance インターフェイスを持つことです。次に、次を使用できます。

IDistance distanceArg = arg as IDistance;
if (distanceArg != null)
{
    Distance distance = distanceArg.ToDistance();
}

既にボックス化された値を取得しているため、インターフェイスを使用しても余分なボックス化などは発生しません。各ToDistance実装は、おそらく暗黙の変換を使用できます。

public Distance ToDistance()
{
    return this;
}

...または、変換を使用することもできますToDistance

于 2010-10-21T13:36:12.160 に答える
2

ええ、それはあなたが生きなければならないことの1つにすぎません。

整数をオブジェクトに押し込むと、同じことが起こります。

int a = 0;
object b = a;
int c = (int)b; // this works
short d = (short)b; // this fails
short e = (short)(int)b; // this works
于 2010-10-21T13:34:48.997 に答える