5

汎用コンバーターを作成しています

これが汎用コンバーターのサンプルコードです

bool TryReaderParse<TType>(object data, out TType value)
{
    value = default(TType);
    Type returnType = typeof(TType);
    object tmpValue = null;

    if (returnType == typeof(DateTime))
    {
        tmpValue = StringToDatetime(data.ToString());
    }
    else if (returnType == typeof(DateTime?)) // THIS IF FIRES
    {
        tmpValue = StringToNullableDatetime(data.ToString());
    }

    value = (TType)Convert.ChangeType(tmpValue, returnType);  // THROWS
}

public DateTime? StringToNullableDatetime(string date)
{
    DateTime? datetime = null;
    if (!string.IsNullOrEmpty(date))
    {
        datetime = DateTime.Parse(date, new CultureInfo(Resources.CurrentCulture));
    }

    return datetime;
}

そして、これは私がそれを使用する方法です:

void foo()
{
    DateTime? date = null;
    TryReaderParse<DateTime?>("25/12/2012", out date);
}

DateTimeスローされた例外は、からに変換できないことを示していますNullable<DateTime>。このメソッドはnull許容型を作成して返すので、なぜキャストが失敗するのでしょうか。

最後に、この特定の例では、null許容のDateTimeが必要です。

編集問題は、StringToNullableDatetimeメソッドがを返しDatetime?、キャストがから変換できないと言っていることですDatetime

StringToNullableDatetimeメソッドはnull許容の日時を返すのでConvert.ChangeType、渡された引数がnull許容であることをが認識できない可能性はありますか?

追伸 私は反対のことをするこのような答えを読みました(nullableからのキャスト)。

4

3 に答える 3

18

DateTimeスローされた例外は、からに変換できないことを示していますNullable<DateTime>。このメソッドはnull許容型を作成して返すので、なぜキャストが失敗するのでしょうか。

良い質問。ボックス化されたnull許容型などがないため、これは失敗します。aをに変換するDateTime?object、がnullの場合はnull参照を取得するかDateTime?、ボックス化されたaを取得しますDateTime。ボックス化されたnull許容構造体を取得することはありません。そのような事はありません。

したがって、そのボックスにはnullまたは有効なDateTimeが表示されます。次に、Convertにそれをnull許容のDateTimeに変換するように指示しますが、Convertはその方法を知りません。

私のアドバイスは、この攻撃ラインを完全に放棄することです。このコードは、ジェネリックスを乱用する境界線です。ジェネリックの特定のタイプに切り替えるときはいつでも、コードはジェネリックではなくなりおそらく間違っています。日時に対して「試行」スタイルのメソッドを実行する場合は、次のように記述します。

DateTime? TryReadDateTime(object data)
{
    ... return null if the object cannot be read as a datetime ...
}

あなたが読むつもりのすべてのタイプのためにそのようなメソッドを書いてください。ユーザーはむしろ次のように書きます。

DateTime? d = TryReadDateTime(data);
if (d != null) ...

よりも

DateTime d;
bool b = TryRead<DateTime>(data, out d);
if (b) ...
于 2012-04-25T15:23:48.950 に答える
0

ドキュメントから、この行は次の場合にエラーになります。

値はnullで、conversionTypeは値型です

Nullable<T>は構造体であり、したがって値型であるため、値がnullの場合、このメソッド呼び出しを使用することはできません。あなたはすでに日付を別々に扱っているのに、なぜChangeTypeとにかくそのような場合に使用するのですか?

于 2012-04-25T15:05:31.660 に答える
0

nullables、ジェネリックス、ボクシングの相互作用の仕方は奇妙です。次の2つの方法を定義する方がよい場合があります。

bool TryReaderParse(object data、out TType value);
bool TryReaderParse(object data、out TType?value)where TType:struct;

2番目の方法では、コードでaTTypeを生成し、問題なく割り当てることができTType?ます。

于 2012-04-25T15:20:20.497 に答える