2020年11月26日
川俣晶の縁側ソフトウェアC# コーディング How To total 447 count

【入門級】時間比較が失敗する場合

Written By: 川俣 晶連絡先

 サンプルソースは現在時刻の1秒後を算出し、現在時刻がそれの時間になるまで待ちます。(実際に使う時は、ただ待つだけではなく何かの処理を行います)

 本来は1秒ごとに現在時刻が表示されることを意図していますが何も出力されません。

 なぜでしょう?

 理由は、.NETの日付時刻は秒より下の桁の時間も管理しており、その微細な値が完全に一致することはほとんどないからです。

 ですから、.NETの日付時刻つまりDateTimeやDateTimeOffset型を比較する場合には、等価比較ではなく不等号で比較しなければなりません。サンプルソースにもコメントで動作するコードを入れてあります。このように、ある瞬間を越えたことを判定するようにすれば、意図した通りに1秒ごとに時間が表示されるようになります。

罠の数々 §

  • ただ待つだけならTask.Delayメソッドなどを使った方が良い。待っている間、リソースをいろいろ解放してくれて、消費電力が減り発熱も減る
  • Task.Delayメソッドは非同期なので、待ちながら別の処理を同時に実行することもできる

参考リンク §

DateTime 構造体

DateTimeOffset 構造体

 秒より下の桁がどう扱われているか、上記のリンクから辿って調べてみよう。ついでに、良く似たDateTime 構造体とDateTimeOffset 構造体の役割の違いも調べてみよう。

リポジトリ §

https://github.com/autumn009/cshowto

TimeEqual §

using System;

class Program

{

    static void Main()

    {

        for (; ; )

        {

            var target = DateTimeOffset.Now.AddSeconds(1.0);

            for (; ; )

            {

                if (DateTimeOffset.Now == target) break;

                // ↓正しいコード

                //if (DateTimeOffset.Now > target) break;

            }

            Console.WriteLine(DateTimeOffset.Now);

        }

    }

}

実行結果

(何も出力されない。よほど運が良ければ何か出る可能性はある)

COOL C# CREW

C#ハウツー連載の解説増量、カラーのソース、新規書き下ろし追加の読みやすい単行本はこちら。

C#ハウツー: 逆引き入門・こんな機能はどう書くの?