C# 入門講座
Visual Studio 2005 Visual Studio 2008 Visual Studio 2010 Visual Studio 2012 Visual Studio 2013 Visual Studio 2015 Visual Studio 2017 Visual Studio 2019

第6回 文字・数値・日付のあつかい

この記事が対象とする製品・バージョン (バージョンの確認方法)

VS2019 Visual Studio 2019 対象です。
VS2017 Visual Studio 2017 対象です。
VS2015 Visual Studio 2015 対象です。
VS2013 Visual Studio 2013 対象です。
VS2012 Visual Studio 2012 対象ですが一部画面が異なる場合があります。
VS2010 Visual Studio 2010 対象ですが一部画面が異なる場合があります。
VS2008 Visual Studio 2008 対象ですが一部画面が異なる場合があります。
VS2005 Visual Studio 2005 対象ですが一部画面が異なる場合があります。
VS.NET 2003 Visual Studio 2003 対象外ですがほとんどの操作は同じなので参考になります。
VS.NET 2002 Visual Studio (2002) 対象外ですがほとんどの操作は同じなので参考になります。

概要

・プログラムの中では文字列・数値・日付は別々の方法であつかう必要がある。

・ " で囲まれた部分は文字列となる。

・ 日付と時刻を表現するには DateTime オブジェクトを使用する。

・文字列・数値・日付の基本的なあつかい方

 

1.型

 

プログラムの経験がほとんどない方は意外に思われるかもしれませんが、プログラムの世界では文字と数値と日付は明確に区別されます。たとえば、文字をデータベースに書き込むときと、日付をデータベースに書き込むときとでは違う仕組みを使います。日付を書き込む仕組みを使って文字を書き込もうとすると多くの場合エラーになります。

そのため、プログラムの中で文字・数値・日付をあつかう場合(つまりほとんどの場合)はこれらの取り扱いをちゃんと知っていなければなりません。

今回はこのような文字・数値・日付の取り扱い方の違いと、簡単な取り扱い例を説明します。

このような区別を「型」(かた)を呼びます。データ型とも言います。

型には文字・数値・日付の他にもたくさんのものがあります。また、「数値」と一口に言ってもコンピューター内部の処理の違いによって細かくはいくつかの型に分かれます。(整数型・長整数型・十進型・浮動小数点型など)。

「文字」についても文字型と文字列型は別の型です。「文字」といった場合は1文字、「文字列」と言った場合は1文字以上の連続する文字を指します。プログラムの中で扱う文字は99%「文字列」です。「文字列」という言葉は重要なので覚えておいてください。

 

初心者の方にはなぜ型を区別しなくてはならないのか疑問に感じる方もいらっしゃるでしょう。確かにこれらを区別しないという考え方もあります。しかし多くのプログラマたちはこれらを区別した方がプログラムにとって大きなメリットがあると考え、現在C#を含めほとんどのプログラム言語では型を区別します。

型を区別する最大のメリットは間違いの防止です。今の時点ではピンとこないかもしれませんが、C#自体がこれらを区別してあつかうときに最高の性能・機能を発揮するように作られているので「郷に入れば郷に従え」です。とりあえず、メリットが見えなくても割り切って理解してみてください。

発展 発展学習  -  区別する別の理由

発展学習では意欲的な方のために現段階では特に理解する必要はない項目を解説します。

コンピューター上では1文字1文字に「文字コード」と呼ばれている数値が割り当てられており、たとえば「A」は65, 「B」は66といった具合に認識されています。「A」という文字をどこかに保存してから後で取り出す場合、コンピューターには単なる「65」という数字にしか見えず、これを文字として扱いたいのか数値として扱いたいのかの情報がないと「A」として処理すべきか、「65」として処理すべきか区別がつきにくいのです。

日付の場合も実は内部では数値として管理されています。究極的にはコンピュータはすべてのものを「0」か「1」のかたまりとして処理していることがこの遠因になります。

 

2." は文字列を作る

 

今回は少し初心に戻って、素朴なプログラムの性質を考えて見ます。

一緒にプログラムしながら読んでみてください。

 

まずは次のプログラムを見てください。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("こんにちは");
}

 ■リストA-1

これはもうお分かりと思いますが、実行すると画面に「こんにちは」と表示されます。実行するにはフォームにボタンを1つ貼り付けてください。

 

このプログラムは次のように書くこともできます。

private void Button1_Click(object sender, EventArgs e)
{
    string st;
    st = "こんにちは";
    MessageBox.Show(st);
}

■リストA-2

実行するとリスト1とまったく同じ動作をすることがわかります。

st = "こんにちは";
MessageBox.Show(st)

この部分をみれば、特に知識がなくても感覚的に納得できますよね。stが「こんにちは」という文字列を表しているわけですね。

ここで stは変数と呼ばれるもので、x でも y でも hello でも自分で好きな名前を付けることができます。名前をつけているのが1行目のstring stの部分です。変数については別の機会に説明しますのでここでは1行目は特に気にしないで下さい。今回はこの1行目よりも「こんにちは」などの文字の方がテーマです。

発展 発展学習  -  string st の意味

発展学習では意欲的な方のために現段階では特に理解する必要はない項目を解説します。

でも、意欲的な方のために少しだけ説明しておきます。

変数は使用する前に、その変数を使用することを準備をすることになっています。これを宣言といいます。string st (読み方:string = ストリング)の行がこれに該当します。

宣言は型の名前 + 変数の名前で行うのが基本的です。string は文字列型を表すC#のキーワードです。

そのため string st と書くと文字列型の変数 st を宣言していることになります。

 

さて、プログラムをさらに改造して次のようにしてみてください。

//これはおかしな例です。
string st;
st = "こんにちは";
MessageBox.Show("st");

■リストA-3

前の例との違いはMessageBox.Show(st)Stの前後に " が付いている点です。この状態で実行すると今度は「こんにちは」ではなく、「st」と表示されます。

このように 記号 " (ダブルクォーテーション)には特別な意味があります。 " ではさまれているものは、意味のない文字列 としてあつかわれるのです。

ですから、次のプログラムでは「MessageBox」と表示されます。


MessageBox.Show("MessageBox");

■リストA-4

一方、次のプログラムはエラーになります。

//これはエラーです。
MessageBox.Show(MessageBox);

■リストA-5

リストA-4ではMessageBoxの前後が " でくくられているのでMessageBoxは意味のない文字列として扱われますから問題ありません。リストA-5ではMessageBoxの前後に " がありませんので MessageBoxは意味のある命令として扱われます。そうするとMessageBox.Show(MessageBox)というプログラムはキーワードの使い方がおかしいのでエラーになってしまうわけです。

メモ メモ  -  コメント

プログラム内で // から始まる行は コメント となり緑色で表示されます。リスト A-5 の最初の行はコメントです。

コメントはプログラムの一部ではなく、人間用のメモです。プログラムではないので実行されることはなく、何でも書くことができます。

 

別の視点でも眺めてみましょう。次の例はエラーになります。

string st;
st = こんにちは;
MessageBox.Show(st);

 ■リストA-6

どうしてエラーかというと、「こんにちは」に " がついていないので、「こんにちは」が意味のある命令として解釈されるからです。しかし実際にはC#には「こんにちは」という命令はありません。ですからエラーになるのです。

この " の性質を初級プログラマーはよく覚えておいてください。

 

3. + は文字列をつなぐ

 

では、次のプログラムを見てください。

private void Button1_Click(object sender, EventArgs e)
{
    string st1;
    string st2;
    string st3;

    st1 = "源";
    st2 = "義家";
    st3 = "頼朝";

    MessageBox.Show(st1 + st2);
    MessageBox.Show(st1 + st3);
}

■リストB-1

このプログラムを実行すると、はじめに「源義家」と表示され、次に「源頼朝」と表示されます。

源義家は平安時代の武将で、後三年の役で活躍しました。義家の孫の孫が平家を打ち破って鎌倉幕府を開いた源頼朝です。

リストB-1を見れば分かるとおり、表示する文字列は 記号 + を使ってプログラム中で合体させています。

変数と文字列

文字列の結合

■図1

このように + を使うと文字列を結合させることができるのですが、これも感覚的に特に難しいということはないでしょう。

リストB-1は次のように書くこともできます。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("源" + "義家");
    MessageBox.Show("源" + "頼朝");
}

■リストB-2

もちろん、リストB-2のようなプログラムを実際に見かけることはないでしょう。"源" + "頼朝" と書くくらいならはじめから"源頼朝"と書くからです。リストB-2はあくまでのこういうこともできるというサンプルです。

さて、もう少し複雑にした次の例を考えて見ましょう。

private void Button1_Click(object sender, EventArgs e)
{
    string st1 = "義家";
    string st2 = "頼朝";
    string st3 = "平安";
    string st4 = "鎌倉";

    MessageBox.Show("源" + st1 + "は" + st3 + "時代に死にました。");
    MessageBox.Show("源" + st2 + "は" + st4 + "時代に死にました。");
}

■リストB-3

こうなってくると、どれが " の中にあって どれが " の外にあるのかとても分かりにくいですね。初心者はこのようなときに " の使い方を間違ってよくエラーになるようです。皆さんも気をつけてください。Visual Studio 2005以上ならば " の中にある文字は茶色く表示されるので少しはわかりやすくなっています。

文字列の結合

■図2

文字列の結合が複雑になってくるとプログラムが見にくくなってくるので、Visual Studio 2013(C# 6.0)以上では文字列補間という機能が導入され、さらに簡単な書き方ができるようになっています。

次の例はリストB-3と同じ結果になります。

private void Button1_Click(object sender, EventArgs e)
{
    string st1 = "義家";
    string st2 = "頼朝";
    string st3 = "平安";
    string st4 = "鎌倉";

    MessageBox.Show($"源{st1}{st3}時代に死にました。");
    MessageBox.Show($"源{st2}{st4}時代に死にました。");
}

■リストB-4

文字列補間機能を使う場合、+ を使わないで文字列を結合できます。リストB-4のように文字列の中に { } で囲んで変数を埋め込むことができます。

先頭の " の前に $ が付いているのがポイントで、$をつけると、文字列補間機能を使用するという意味になります。$ をつけないと通常の文字列になるのでこの例では「源{st1}は{st3}時代に死にました。」などと表示されます。

 

4.いろいろな文字列

 

4−1.改行の書き方あれこれ

C#では、次のようにして改行を表現することができます。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show(@"あいうえお
かきくけこ
さしすせそ");
}

■リストC-1

文字列の改行

この例では文字列の先頭に @ がついていることに注意してください。@ がついている文字列を逐語的文字列(ちくごてきもじれつ)と呼びます。逐語的文字列の場合C#はできるだけ、プログラムに書いてある通りの文字列として解釈してくれます。

 

特別な値 Environment.NewLine (読み方:Environment = エンバイロメント、NewLine = ニューライン)を使って改行を表現することもできます。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("あいうえお" + Environment.NewLine + "かきくけこ" + Environment.NewLine + "さしすせそ");
}

■リストC-2

これを実行すると、Environment.NewLine の位置で改行され、次のように表示されます。

 

 

さきほどの文字列補間機能と組み合わせて次のように書くこともできます。上の例よりは少しだけプログラムが短くなります。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show($"あいうえお{Environment.NewLine}かきくけこ{Environment.NewLine}さしすせそ");
}

文字列補間機能を使う場合は文字列の先頭に $ をつけるのをお忘れなく。

 

C#ではある程度自由にプログラム自体を複数行に分けて書くこともできるので、プログラムの1行が長くなってしまうようならばこのように書くこともできます。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("あいうえお" + Environment.NewLine
                  + "かきくけこ" + Environment.NewLine
                  + "さしすせそ");
}

 長い行のどこを改行すればプログラムが見やすくなるかはプログラマー個人個人の美意識によります。

Environment.NewLineの良いところは、OSによる改行コードの違いを吸収してくれるところです。WindowsとLinuxとでは改行コードが異なるのですが、Environment.NewLineは実行した環境に合わせた改行コードを使ってくれます。

メモ メモ  -  OSと改行コード

Windowsの改行コードはCR + LFです。Linuxの改行コードは LF です。MacはOS9まではCR、それ以降はLFが改行コードです。C#はLinuxやMac上でも実行できるので、複数OSで改行を扱うプログラムを作成する場合は注意が必要です。

OSごとに改行コードが違っていて不便なので、高機能なテキストエディターでは各OSの改行コードの違いを吸収してどのOSで実行しても改行して表示してくれるものもあります。しかし、これはテキストエディターが気を利かせて人間向けに表示してくれるだけであり、内部で使用されている改行コードは異なります。人間向けではなくプログラムからテキストを読み書きする場合は改行コードの違いで思わぬバグになってしまうこともあります。

Environment.NewLineのことをはじめて知ったとしても、これがEnvironmentオブジェクトのNewLineプロパティであるというということは前回の説明を読んでいれば気がつけるかもしれませんね。

 

C#ではこの他に次のように \r\n という特別な文字を使って改行を表すこともできます。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("あいうえお\r\nかきくけこ\r\nさしすせそ");
}

これはC#の先祖であるC言語でも有効な伝統的な表現方法であり、今でも使っているプログラマーは多数います。この記述方法ではOSによる差異は吸収されませんので、Winodwsであれば\r\n、Linuxであれば\r のように自分でプログラム内で改行コードを切り分けるなどの工夫が必要になります。しかし、いろいろなOSで動く必要がないプログラムもたくさんありますから、Windows上でしか動かさないことがわかっている場合などはこの書き方でも問題はありません。

 

4−2.エスケープシーケンス

\r\n のような特別な文字の並びで特別な意味を表現できるものを エスケープシーケンス または エスケープ文字 と呼びます。

エスケープシーケンスを使うことで改行のように通常表現しにくいものを文字列内で表現できます。エスケープシーケンスは複数ありますが必ず \ から始まります。

メモ メモ  -  \ なのは日本だけです

日本語のフォントでは \ は円マークの形になっているのですが、外国用のフォントではこの文字コードに全然違う形の文字が割り当てられている場合があります。英語ではバックスラッシュが割り当てられているので、英語のサンプルなどを見るとエスケープシーケンスが \r\nではなく、\r\n のように見えます。

よく使うエスケープシーケンスは次の通りです。

エスケープシーケンス 意味
\" ダブルクォーテーション
\\ 円マーク (英語フォントではバックスラッシュ)
\r\n 改行(Windows)
\r 改行(LinuxとMacOSX以降)
\n 改行(MacOS9以前)
\t タブ
\u Unicode文字をUTF16で指定

表示する場所が対応していなければ無意味なことがほとんどです。たとえば、改行できない場所で改行は無意味ですし、タブが表示できない場所でタブは無意味です。

MessageBox.Showは改行もタブも表示してくれるので、次のコードは有効です。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("あいうえお\tかきくけこ");
}

このように表示されます。

タブ付きの文字列

文字列内で " や \ を表現したいときもエスケープシーケンスの出番です。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("\"これいくらですか?\"\r\n\"\\1200です。\"");
}

ちょっと普段使わない感じの記号の使い方になってしまいました。実行すると次のようになります。

このレベルになるとパッと見でどうなっているのかわからなくなってしまいますが、あまり心配する必要はありません。今はエスケープシーケンスの説明をしているのであえて複雑な例を紹介していますが、実際のプログラムの中ではこのようなことを記述する必要は通常はないでしょう。というのも、プログラム内でこのように固定の文字列を記述して表示するということはほとんどないからです。

\Uは他とはちょっと使い方が異なっており、これに続けてUnicodeの文字コードをUTF16で入力します。

次の例ではこれを利用してUnicodeの絵文字からコーヒーを表示します。Unicodeの絵文字に対応したフォントでないと表示できないので、textBox1にフォントを指定するプログラムも含めました。フォントを指定するプログラムは入門講座では説明していませんが、フォント名とフォントサイトを指定するだけです。今回説明したいのはエスケープシーケンスの方なのでここにはあまり深入りしません。プロパティウィンドウを使ってあらかじめフォントをSagoe UI Emojiに設定しておいても良いです。

それから、この例を実行するためにはあらかじめtextBox1という名前のテキストボックスをフォームに配置しておく必要があります。念のため。

private void Button1_Click(object sender, EventArgs e)
{
    textBox1.Font = new Font("Segoe UI Emoji", 24);
    textBox1.Text = "\u2615いかがですか?";
}

Unicodeの絵文字が表示されているTextBox

ところで、わざわざ文字コードで書かなくてもプログラムに直接絵文字を入力してしまうこともできます。

プログラムに直接絵文字を埋め込むこともできます

コーヒーの絵がさきほどと違うのはフォントの違いによるものです。

 

4−4.パス

Windowsのファイルのパスはフォルダーの区切り文字に \ を使用しているため、プログラムの中で何も考えずにパスを扱うと C# はエスケープシーケンスだと解釈してしまいます。

たとえば、次のプログラムは WriteAllTextメソッド(読み方:WriteAllText = ライトオールテキスト)を使って、ファイルに文字列を書き込もうとしているものです。

対象のファイルのフルパスと書き込む内容を両方文字列の引数で指定する必要があります。

private void Button1_Click(object sender, EventArgs e)
{
    //この例はエラーになります。
    System.IO.File.WriteAllText("C:\test\text.txt", "あいうえお");
}

でも、この例だと \t がタブを表すエスケープシーケンスになってしまうので、意図したようなフォルダーとファイルを意味しません。そもそもパスにはタブを含むことができないので実行するとエラーになります。

簡単な解決方法はさきほどでてきた逐語的文字列です。文字列の先頭に @ をつけて、逐語的文字列にすればほとんどのエスケープシーケンスは無効になり、ファイルのパスは書いたままに解釈されます。

次の例は正常に動作します。

private void Button1_Click(object sender, EventArgs e)
{
    System.IO.File.WriteAllText(@"C:\test\text.txt", "あいうえお");
}

 

4−5.少し整理

いろいろ出てきて話が複雑になってきました。ちょっとまとめましょう。C#の文字列には3種類あります。

1つ目は、" " で囲まれた普通の文字列です。2つ目は $" " で囲まれた文字列補間機能付きの文字列です。3つ目が @" " で囲まれた逐語的文字列です。この3つで全部です。

$ と @ が両方付く場合もあるので、これも入れると4種類です。この場合、文字列補間機能と逐語的文字列の両方の性質があります。C#上級編の勉強をしてもこれ以上種類は増えません。

文字列の種類 \から始まるエスケープシーケンス
(\t や \r\n など)
文字列補間
( {st1} のようなもの)
通常の文字列 "こんにちは" ○ 機能します × 機能しません
文字列補間機能付きの文字列 $"こんにちは、{name}さん" ○ 機能します ○ 機能します
逐語的文字列 @"C:\test" × 機能しません × 機能しません
文字列補間機能付きの逐語的文字列 $@"C:\{folderName}" × 機能しません ○ 機能します

なお、$ と @ の両方をつける場合は $@ の順番でつけるのが良いです。2019年リリースの C# 8.0 からはどちらの順番でも使用できるようになりましたが、それより前のC#では $@ の順番でしか使えないのであわせておくのがよいでしょう。

ここで説明していない文字列の使い方もまだまだあるのですがここではあまり深入りしません。概要を理解してもらえればよいです。

その他 一言  - これ覚えてなくていいですよ。試験には出ません。

一応、「こんな感じのものがあるんだなぁ」くらいの感想を持ってもらえれば私の意図は達成です。使い方がわからなければその時調べていけばよいのです。最初からルールを覚えている人など多分居ないと思います。

 

 

 

5.数値

 

5−1.数値は直接記述する

数値をあつかう場合は文字列と違って " をつけずに直接書きます。

たとえば、次のプログラムは正常に動作し、実行すると 627 と表示されます。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show(627.ToString());
}

■リストD-1

627の後ろに ToString とついているのは、627を文字列に変換するためです。

MessageBoxに表示できるのは文字列だけなので、文字列以外のものを表示したい場合は ToStringメソッド(読み方:ToString = トゥーストリング)で文字列に変換するなどします。

 

このプログラムは次のように書くこともできます。

private void Button1_Click(object sender, EventArgs e)
{
    decimal x = 627;
    MessageBox.Show(x.ToString());
}

■リストD-2

decimal xの方は今回のテーマではないのであまり気にしないでください。簡単に説明すると数値型の変数 x を宣言しています。 

数値型にも何種類かあるのですが、decimal (読み方:decimal = デシマル)で宣言すると数値型の中でも「十進型」(じゅっしんがた)という型になり、整数も小数も表現できる変数になります。

 

数値の場合は +, -, *, / などを使って計算することもできます。 キーボードには掛け算の「×」と割り算の「÷」がないので代わりに * が掛け算、 / が割り算を表しています。

これらの記号を使った例は次の通りです。

private void Button1_Click(object sender, EventArgs e)
{
    decimal x = 815.6M;

    decimal a1 = x + 3;
    MessageBox.Show(a1.ToString());

    decimal a2 = x - 3;
    MessageBox.Show(a2.ToString());

    decimal a3 = x * 3;
    MessageBox.Show(a3.ToString());

    decimal a4 = x / 3;
    MessageBox.Show(a4.ToString());
}

■リストD-3

変数 x を decimal で宣言しているので小数もちゃんと扱えます。

ただ、よくみると x に 815.6 をセットするときに、後ろに「M」がついているのがわかります。

このMは 815.6 という値を decimal として扱うということをC#に指示する意味です。このように型を明示する意図で使う文字がいくつかあり「型のサフィックス」と呼ばれます。

数値にMがついている

 

リストD-2では、この M が必要なかったのは値が整数だからです。値が小数の場合、C#は浮動小数点型(double)という型であると判断してしまいます。しかし、私たちはdecimalにしたいので、C#に、これはdecimalだと伝えるためにMをつけます。

メモ メモ  -  浮動小数点型(double)はお勧めしません

数値型にはいろいろあり使いどころが違います。浮動小数点型には良い面もありますが、小数を含む計算で誤差が出る場合があります。decimal型は誤差がでません。だから、何を使うか迷ったらdecimal型を使うことをお勧めします。小数がなく整数だけであればintをお勧めします。型についての詳しい説明は初級講座で行う予定です。

※有限桁数を処理しているコンピューターの特性上表現できない限界はだいたいあります。decimalでも整数部・小数部あわせて28桁以上の値は処理できない場合があります。

 

 

話を元に戻しましょう。

+, -, *, /のような計算記号のことをC#では「演算子」(えんざんし)と呼びます。C#で使える計算用の演算子の表を載せておくので参考にしてください。

演算子 通称 機能
+ プラス・たす たし算
- マイナス・ひく ひき算
* アスタリスク・かける かけ算
/ スラッチュ・わる わり算
== イコール・ダブルイコール・は(わ) 等しいか調べる
% パーセント わり算をして、「あまり」を返す。

これ以外にもさまざまな演算子があります。

 

その他 一言  == の読み方

== の具体的な使用方法は初級講座で説明する予定です。私はこの記号を「イコール」と呼ぶことが多く、強調したいときは「イコールイコール」と呼んでいるのですが少数派かもしれません。


下記サイトでは「== の発音は "is equal to"」と書いてあり、直訳すると「は…に等しい」という意味なので、日本語では「は(わ)」が適切そうです。例 x == 2 → x は 2
https://www.dummies.com/programming/c/how-to-use-the-if-function-in-c-programming/


「Programming Like a Pro for Teens」という書籍の83ページ目には「x == 5; は "X equlas 5"と発音する」と書いてあります。これによると「イコール」は良さそうです。
https://books.google.co.jp/books?id=CY0LAAAAQBAJ&pg=PA83&lpg=PA83&dq=%22pronounce%22+%22double+equal%22&source=bl&ots=853UuvBJVw&sig=ACfU3U0-ld4-ucIfI2xKnxVmA6p3Lz8djA&hl=en&ppis=_e&sa=X&redir_esc=y#v=onepage&q=%22pronounce%22%20%22double%20equal%22&f=false

 

5−2.演算子と型

ところで、文字列の説明をしたときに「+」は文字列をつなぐと説明しました。数値の説明をしたときには「+」はたし算の記号であると説明しました。

このように同じ記号でも型によって意味が変わります。特にたし算と文字列の結合はどちらもプログラムでよく出てくるので + 記号の取り扱いに初心者は注意です。

次のプログラムはなんと表示されるかわかりますか?

このプログラムでは変数testの型の部分に var (読み方:var = バー)と書いています。varは特殊なキーワードで、簡単に説明すると変数の方はC#におまかせするという意味です。変数の宣言と値のセットを同時に行う場合だけvarを使って変数の型をC#にまかせることができます。Visual Studio 2008に搭載のC# 3.0以上でvarは使用できます。

private void Button1_Click(object sender, EventArgs e)
{
    var test = "2" + "3";
    MessageBox.Show(test.ToString());
}

このプログラムでは + の前後の "2" と "3" は " で囲まれているため文字列です。そのため + の意味は文字列の結合になりますので、「23」と表示されます。

C#はtestを文字列型と判断します。

それでは次のプログラムはどうでしょうか?

もうどこに注目すればよいかわかりますよね?

private void Button1_Click(object sender, EventArgs e)
{
    var test = 2 + 3;
    MessageBox.Show(test.ToString());
}

このプログラムでは 2 と 3 が " に囲まれていないので数値と判断されます。そのため + はたし算ですから、「5」と表示されます。

ちなみに、このケースではC#はtestを整数型(int)と判断します。

 

では、次のプログラムはどうでしょうか?

private void Button1_Click(object sender, EventArgs e)
{
    var test = 2 + "3";
    MessageBox.Show(test.ToString());
}

これは、もう入門講座の範囲をかなり超えてしまっています。

そもそもこのような紛らわしいプログラムは書くべきではありません。あなたがこのようなプログラムを書いたら先輩はNGを出すと思いますよ。

それでも実行はできます。この例では「23」と表示されます。文字列の方が"3"だから一瞬迷ってしまいますが、もし2 + "A"だったら、エラーになるか、「2A」になるかしか考えられないですよね。

6.日付と時刻

 

6−1.日付と時刻の表示形式

C#では日付と時刻を表す特別な表現方法は用意されていません。

特別な表現方法が用意されていない場合は、オブジェクトを使用することになります。日付と時刻の場合 DateTime (読み方:DateTime = デイトタイム)というオブジェクトが用意されています。

「オブジェクト」全般については初級講座で扱う予定です。ここではDateTimeだけについて扱い方を説明します。

 

次のプログラムは2020年6月27日を表すDateTimeオブジェクトを作成し、文字列として表示します。

private void Button1_Click(object sender, EventArgs e)
{
    //2020年6月27日を表すDateTimeオブジェクトを作成
    DateTime day = new DateTime(2020, 6, 27);

    //文字列として表示
    MessageBox.Show(day.ToString());
}

■リストE-1

「文字列として表示」というところは 初心者に特に注意してもらいたい部分です。詳しく説明しましょう。

日付や時刻を画面に表示したり、印刷したりなど人間向けに表示するとき、それはDateTimeオブジェクトではなく文字列型です。

たとえば、2020年6月27日という日付は1つしかありませんが、これを画面に表示するための形式はたくさんあります。いくつか例を挙げてみます。

このような形式を書式と呼びます。

DateTimeオブジェクトははこのような表示用の書式とは無関係で、1つしかない日付の値自体を表現しています。画面などに表示する日付はDateTimeオブジェクトではなく文字列型です。

DateTimeオブジェクトを文字列型に変換する場合ToStringメソッドを使用します。さきほどのリストE-1でもMessageBoxで表示するときにはToStringメソッドを使って文字列型にしています。

DateTimeオブジェクトはプログラム内での存在

 

日付の値をどのような書式で表示するかは表示するときにプログラマーが指定します。

特に指定をしなかった場合はプログラムを実行しているユーザーのWindowsのコントロールパネルの地域と言語の設定に依存します。

コントロールパネルの地域と言語の設定

プログラムを作成したユーザーではなく、実行しているユーザーである点に注意してください。

つまり、プログラマーが書式を指定しなかった場合、どのように表示されるかプログラマーには事前には予測できないということです。

日本人のWindowsの設定は大体同じだと思いますが、リストE-1を実行した結果何が起こるかは人によって違うかもしれません。私の場合「2020/06/27 0:00:00」と表示されました。

博士のワンポイントレッスン 「なんでわざわざDateTime?」
V太 V太:ちょとまて、ちょとまて!意味がわからないよ。わざわざDateTimeなんて使わないで、最初から文字列で"2020/06/27"と書けばいいんじゃないの?どのように表示されるかもはっきりしているし。
B子 B子:うーん。確かにそうかも。博士、どういうことですか?
V太 博士:うーむ。ちょっと考えてみて欲しい。日常生活の中で「日付」ってどういう風につかっているかのぉ?
B子 えっと、「明日は晴れ」とか、「来週は遠足」とか、「月末は忙しい」とか、「1週間後には返してください」とか、「去年は暑かった」とか、「後300日で東京オリンピック」とか?
V太 「明日」、「来週」、「月末」、「1週間後」、「去年」、「後300日」
V太 DateTimeの機能を使うとそういった日時や期間を簡単に求めることができるのじゃ。文字列にはそういう機能はない。だから、文字列で"2020/06/27"とプログラムしてしまうと、1週間後が何月何日か求めるプログラムを作るのはすごく大変なのじゃ。DateTimeだと AddDaysメソッドを使って1週間後の日付は簡単に求められるぞ。AddDaysの使用例は後で紹介しよう(リスト H-3)。
B子 なるほどねぇ。でも、実際に使ってみるまではピンとこないかも。
博士 他にも日付や時刻ならではの機能というのは結構いっぱいある。日付や時刻がプログラムの中にでてくるのだったら文字列ではなくDateTimeを使うようにの。

 

 

 

6−2.書式指定

 

表示するときに書式を指定する方法はいくつかあります。代表的なのはToStringメソッドの引数を使う方法です。

リストE-1のように引数なしでToStringメソッドを使用すると、どのように表示するかはWindowsの設定によって変わります。

ToStringメソッドに引数をつけると書式を指定できます。これを使えば、どのように表示されるか制御できます。

下記の例では変数に格納した日付を異なる書式で表示しています。

private void Button1_Click(object sender, EventArgs e)
{
    //2020年6月27日を表すDateTimeオブジェクトを作成
    DateTime day = new DateTime(2020, 6, 27);

    //書式指定なし。Windowsの設定で書式化されます。
    MessageBox.Show(day.ToString());

    //2020年06月27日
    MessageBox.Show(day.ToString("yyyy年MM月dd日"));

    //20-06-27
    MessageBox.Show(day.ToString("yy-MM-dd"));
}

■リストE-2

書式は引数に独特の文字列で指定します。この文字列のことを書式指定文字列といいます。

書式指定文字列には、yyyyであれば西暦で4桁の年、MMは西暦で2桁の月、Mは西暦で1桁の月のように定められているものを組み合わせて使用します。

よく使う日付の書式は次の表のとおりです。曜日も書式で表現している点は覚えておくと良いと思います。

yyyy 年を4桁 例:2020 HH 24時間制の時間を2桁 例:15
yy 年を2桁 例:20 H 24時間制の時間を1桁または2桁 例:15
MM 月を2桁 例:06 hh 12時間制の時間を2桁 例:03
M 月を1桁または2桁 例:6 h 12時間制の時間を1桁または2桁 例:3
dd 日を2桁 例:27 mm 分を2桁 例:05
d 日を1桁または2桁 例:27 m 分を1桁 例:5
dddd 曜日 例:土曜日 ss 秒を2桁 例:46
ddd 曜日の短縮形 例:土 s 秒を1桁 例:46

・書式指定ではアルファベットの大文字と小文字が区別されるので注意してください。

・「H」だけや「d」だけのように、1文字だけの書式は指定できません。1文字だけ指定する必要がある場合は特別に「%H」や「%d」のように前に「%」を付けます。

参考:カスタム日時書式指定文字列

https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/custom-date-and-time-format-strings

 

メモ メモ  -  標準の書式指定文字列

本文で紹介しているカスタムの書式指定文字列の他に、標準の書式指定文字列というものもあり、もっと簡単に書式を指定できます。しかし、どのような形式になるのか私にはわかりにくいため、私は使用していません。他のプログラマーが使っているところも私は見かけないです。

書式指定文字列が1文字の場合、それは標準の書式指定文字列です。2文字以上ある場合はカスタムの書式指定文字列です。

参考:標準の日時書式指定文字列

https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/standard-date-and-time-format-strings 

 

書式指定文字列の中では定義されていない文字列はそのままその位置に出力されます。たとえば、「中」・「学」・「校」という文字は書式として定義されていないため、day.ToString("中学校") は day が何月何日でも「中学校」と表示されます。

day.ToString("中MM学校") だと MM は月2桁と定義されているため、たとえば、「中08学校」となります。すべての漢字を含めほとんどの文字は書式として定義されていないため自由に使用できます。「年」「月」「日」「時」「分」「秒」も自由に使用できます。

\ は特別な効果があり、直後の文字を書式指定文字ではない通常の文字として扱います。たとえば、ToString("yyyy")は年4桁になりますが、ToString(@"\y\y\y\y")はそのまま「yyyy」と出力されます。この文字列には @ がついていて、先ほど説明した逐語的文字列になっている点に注意してください。

日付の区切り文字である / は文化によっては - として出力される場合があると思います。どの環境でも確実に / と表示するためにはToString(@"yyyy\/MM\/dd")のようにエスケープを付けて \/ と書きます。

時刻の区切りによく使われる : についても同様です。

 

7.和暦と文化

 

日付の表示や値は文化により異なります。

日本人は西暦としては一般的にグレゴリオ暦を使用しており、これは世界の多数派です。

しかし、世界にはそうでない文化もあります。

たとえば、日本人にとっての2020年6月27日は、驚くべきことにサウジアラビアでは1441年11月6日です。

また、同じ日付を日本人は 令和2年6月27日 とも表現するかもしれません。これは元号のことを知らない外国人にはやはり驚かれるでしょう。

メモ メモ  -  イスラム暦 ヒジュラ

サウジアラビアの暦はヒジュラ暦と呼ばれます。イスラム教の創始者ムハンマドと信者たちがメッカから移住した西暦622年がヒジュラ元年です。1年はおおむね354日なので、日本で使われている1年が365日のカレンダーからどんどん日付がずれていきます。そういうわけでグレゴリオ暦2020年6月27日はヒジュラ暦1441年11月6日となります。

なお、2018年頃にサウジアラビアではグレゴリオ暦の採用を決定したそうですので、今では本文中にある2020年6月27日はサウジアラビアでも2020年6月27日と表記するのかもしれません。正直実情はわからないです。

 .NETは世界中で使用できるように設計されており、この「文化」を設定などで指定したり変更したりできます。プログラム自体はグレゴリオ暦で記述することになっているので、世界中どこに言っても変わりません。それを表示するときはそれを実行しているコンピューターの文化や、プログラムで指定した文化で表示されます。だから、サウジアラビア用のWindowsでMsgBox(#6/27/2020#) を実行すると、おそらく「1441/11/6」と表示されるはずです。

 

日本の文化を適用すれば平成や令和などの和暦をC#で扱うことも可能です。ToStringメソッドの第2引数には文化を指定できるので、ここで日本の和暦の文化を指定しましょう。

ただ、このプログラムは入門講座としては少し高度なので、理屈の説明はここでは割愛します。

プログラムは次のようになります。

private void Button1_Click(object sender, EventArgs e)
{
    //2020年6月27日を表すDateTimeオブジェクトを作成
    DateTime day = new DateTime(2020, 6, 27);

    //日本の文化を取得して、カレンダーに和暦を指定
    System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("ja-JP", true);
    culture.DateTimeFormat.Calendar = new System.Globalization.JapaneseCalendar();

    //02/06/27 (yyyyが西暦ではなく令和の年になる)
    MessageBox.Show(day.ToString("yyyy/MM/dd", culture));

    //令和2年6月27日(ggで「令和」)
    MessageBox.Show(day.ToString("ggy年M月d日", culture));
}

■リストF-1

日本の和暦の文化を適用した状態では yyyy は和暦の年になります。yy と書いても同じです。「平成」や「令和」などの元号の名称はggです。

なお、2019年を和暦で表示すると令和1年ではなく、令和元年になります。ちなみに、令和は2002年に.NETがリリースされてから世界で始めて発生した暦の変更でした。

 

8.日付についてその他

 

8−1.現在日付

DateTimeオブジェクトのNowプロパティ(読み方:Now = ナウ)は常にその時の日付を表しているので重宝します。使い方も簡単です。

private void Button1_Click(object sender, EventArgs e)
{
    DateTime day = DateTime.Now;
    MessageBox.Show(day.ToString());
}

 ■リストG-1

コンピュータが管理している現在の日付・時刻のことを「システム日付」、「システム時刻」とも呼びます。

 

8−2.時刻

「日付」という言葉はC#では時刻も含みます。ここまでの例では時刻は扱いませんでしたが、日付と同じようにDateTimeオブジェクトを生成して、書式指定を使って文字列にできます。

private void Button1_Click(object sender, EventArgs e)
{
    // 2020年6月27日13時14分15秒
    DateTime day = new DateTime(2020, 6, 20, 13, 14, 15);

    //13:14:15 と表示します。
    MessageBox.Show(day.ToString(@"HH\:mm\:ss"));
}

■リストG-2

 

9.メソッドとプロパティ

 

既にいくつか登場しましたが、文字列・数値・日付もメソッドとプロパティをもっています。

たとえば、文字列のLengthプロパティ (Length = レンクス)は文字列の文字数を表します。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("こんにちは".Length.ToString());
}

■リストH-1

この例では、「5」と表示されます。Lengthは長さを表しているので値は数値型です。数値型はそのまま表示できないのでToStringを使って文字列型にしています。

 

ToUpperメソッド (ToUpper = トゥーアッパー)は英語の小文字をすべて英語の大文字に変換します。

private void Button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("Hello".ToUpper());
}

■リストH-2

この例では、「HELLO」と表示されます。

 

DateTimeにもさまざまな機能があります。

代表的な利用例をいくつか紹介します。

private void Button1_Click(object sender, EventArgs e)
{
    DateTime testDay = new DateTime(2020, 6, 27);

    //次の日 → 2020/6/28
    DateTime nextDay = testDay.AddDays(1);
    MessageBox.Show(nextDay.ToString());

    //日付だけ → 27
    int day = testDay.Day;
    MessageBox.Show(day.ToString());

    //年だけ → 2020
    int year = testDay.Year;
    MessageBox.Show(year.ToString());

    //日付の引き算 7/1 までは 4日ある
    DateTime lastDay = new DateTime(2020, 7, 1);
    int diff = (lastDay - testDay).Days;
    MessageBox.Show(diff.ToString());
}

■リストH-3

最後の日付の引き算はまだ登場していない新しい文法で記述してみました。

日付の情報や操作にはいろいろあるので現段階では「こういったこともできる」という程度に覚えておいてください。もし文字列であればこのような日付の処理は簡単にはできません。

 

他にも便利なメソッドやプロパティがいろいろとありますが、数が多すぎるので、必要に応じて説明していくことにします。

文字列型・DateTimeのメンバー(メソッドやプロパティなど)の一覧は下記で確認できます。現段階ではまだ知識がたりないので公式ドキュメントの解説の意味がわからないと思います。公式ドキュメントが読めるくらいの知識がたまれば独学でどんどんメンバーを使うことができるようになります。今後参考にしてください。

文字列型のメンバー

https://docs.microsoft.com/ja-jp/dotnet/api/system.string?view=netframework-4.8#%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3

DateTimeのメンバー

https://docs.microsoft.com/ja-jp/dotnet/api/system.datetime?view=netframework-4.8#%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3