0

環境: Visual Studio 2015

TimeZone: : UTC + 7:00、バンコク

問題: DateTimeOffset の null 許容変数 (DateTimeOffset?) で、Null 条件付き演算子を使用すると例外が発生します。つまり、値が NULL の場合でもメソッドが呼び出されます。例外が発生します。

クエリ: Null 条件演算子を使用しないか、演算子の代わりに GetValueOrDefault を使用することで解決できますが、すべての UTC + TimeZones で例外が発生する理由を理解したいのですが、UTC - TimeZones でうまく機能します

コード:

var dateTimeMinimum = DateTime.MinValue;
    var value = (object)dateTimeMinimum; // Mimic the WPF converter behavior
    var a1 = value as DateTimeOffset?; // This works
    if (a1 != null)// This works as it won't execute the code in the 'if'loop
    {
        var b1 = (a1 as DateTimeOffset?)?.ToLocalTime();
    }

var dto = (value as DateTimeOffset?)?.ToLocalTime() ?? (DateTime)value;// This breaks with following exception

ここに画像の説明を入力

編集

コードを修正するには多くの方法があることを理解しています。

    DateTime dateTimeMinimum = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);

ただし、null 条件演算子を使用しない場合のクエリは次のとおりです。

var a1 = value as DateTimeOffset?;

例外にはなりません。以下のブログごとに、null 条件演算子が変数をアンラップするためでしょうか

http://www.ninjacrab.com/2016/09/11/c-how-the-null-conditional-operator-works-with-nullable-types/

null条件演算子を使用すると壊れ、DateTimeKind.Utcを使用せずに「as」演算子を使用すると単純なキャストで機能する理由を理解することにもっと興味があります。

EDIT2

これは DateTimeOffset (.NET フレームワーク コード) のコンストラクターで、ValidateOffset メソッドで中断します。ソース- http://referencesource.microsoft.com/#mscorlib/system/datetimeoffset.cs,68b4bb83ce8d1c31

 // Constructs a DateTimeOffset from a DateTime. For Local and Unspecified kinds,
        // extracts the local offset. For UTC, creates a UTC instance with a zero offset.
        public DateTimeOffset(DateTime dateTime) {
            TimeSpan offset;
            if (dateTime.Kind != DateTimeKind.Utc) {
                // Local and Unspecified are both treated as Local
                offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
            }
            else {            
                offset = new TimeSpan(0);
            }
            m_offsetMinutes = ValidateOffset(offset);
            m_dateTime = ValidateDate(dateTime, offset);
        }
4

2 に答える 2

1

問題は、最小日付が UTC 0 であるということです。そのため、UTC が正の場合は、UTC 0 では可能な最小値よりも早くなりますDateTime

簡単に言えば、これを作成することはできません (最小日付 UTC +1):

new DateTimeOffset(DateTime.MinValue, new TimeSpan(1, 0, 0))

DateTimeOffsetこれにより、 12 月 31 日-0001午後 11:00 UTCが作成されるためです。

例外はまさにここで発生します。

var dto = <something null> ?? (DateTime)value;

としてdto推測されるようDateTimeOffsetに、あなたがやっている(DateTimeOffset)(DateTime)valueのは、例外がスローされたときです。そのキャストは、表現できない負の日付を作成しようとします。

次のコードを試して、問題がnull 変数に関連していないことを確認してください。

var dateTimeMinimum = DateTime.MinValue;
var value = (object)dateTimeMinimum; // Mimic the WPF converter behavior
DateTimeOffset dto = (DateTime)value;

アップデート

あなたはまだ私を信じていないので、これを試してください:

var dto = (value as DateTimeOffset?)?.ToLocalTime() ?? new DateTimeOffset();

これは失敗しません。なんで?ToLocalTime実行されておらず、実行されたこともありませんでした。今回ずっと失敗したのは、最小値DateTimeからDateTimeOffset正のタイムゾーンへのキャストです。


ところで、演算子を使用して aDateTimeを a に変換することはできません。これは常に null を返します。その演算子は互換クラス用です。DateTimeOffset?as

結局のところ、これを修正しても、あなたのコードは理解と保守が難しすぎると思います。ここで正確に何をしようとしていますか?

于 2016-09-24T20:58:26.603 に答える