C# 初級講座 |
![]() ![]() ![]() ![]() |
2022/5/1
この記事が対象とする製品・バージョン
![]() |
Visual Studio 2022 | ◎ | 対象です。 |
![]() |
Visual Studio 2019 | ◎ | 対象です。 |
![]() |
Visual Studio 2017 | ◎ | 対象ですが、.NET Frameworkで試してください。 |
![]() |
Visual Studio 2015 | ◎ | 対象ですが、.NET Frameworkで試してください。 |
![]() |
Visual Studio 2013 | ○ | 対象ですが、.NET Frameworkで試してください。 $から始まる補完文字列は扱えません。 |
![]() |
Visual Studio 2012 | ○ | 対象ですが、.NET Frameworkで試してください。 $から始まる補完文字列は扱えません。 |
![]() |
Visual Studio 2010 | ○ | 対象ですが、.NET Frameworkで試してください。 $から始まる補完文字列は扱えません。 |
![]() |
Visual Studio 2008 | ○ | 対象ですが、.NET Frameworkで試してください。 $から始まる補完文字列は扱えません。 |
![]() |
Visual Studio 2005 | ○ | 対象ですが、.NET Frameworkで試してください。 $から始まる補完文字列は扱えません。 |
![]() |
Visual Studio.NET 2003 | △ | 対象外ですが参考にはなります。 |
![]() |
Visual Studio.NET (2002) | △ | 対象外ですが参考にはなります。 |
Visual Studio Code | △ | 対象外ですが参考にはなります。 |
目次
クラスの非共有メンバーを呼び出すには、先にクラスのインスタンスを作成する必要があります。
クラスのインスタンスを作成するにはコンストラクターを呼び出します。コンストラクターを呼び出す代表的な方法は new キーワードを使用することです。
いくつかの非共有メソッドを呼び出して実例を体験してみましょう。
下記の設定で新規プロジェクトを作成してください。
プロジェクトテンプレート | Windows フォーム アプリ |
---|---|
プロジェクト名 | CallMemberLesson2 |
ソリューション名 | CallMemberLesson2 |
フレームワーク | .NET 6.0 |
フォームにボタンを1つ配置してClickイベントハンドラーを使って次のようにプログラムしてみましょう。
もし、Windows フォーム アプリ や Click イベントハンドラーのことがわからなければ入門講座第4回 イベントを逃すなを見てみてください。
namespace CallMemberLesson2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//▼JapaneseCalendarクラスのGetEraメソッドの呼び出し
//GetEraメソッドの戻り値の意味。1:明治, 2:大正, 3:昭和, 4:平成, 5:令和
var calendar = new System.Globalization.JapaneseCalendar();
DateTime targetDate = new DateTime(1920, 6, 27);
int eraNumber = calendar.GetEra(targetDate);
MessageBox.Show(eraNumber.ToString(), "GetEra"); //「2」が表示されます。
//▼DirectoryInfoクラスのCreationTimeプロパティの呼び出し
//フォルダーの作成日を実行時点から1年前に変更します。
//フォルダーのパスはみなさんの環境で存在するものに置き換えてください。
var folder = new DirectoryInfo(@"C:\temp\testfolder");
folder.CreationTime = DateTime.Now.AddYears(-1);
//▼Rectangle構造体のコンストラクターとRightプロパティの呼び出し
Rectangle rect = new Rectangle(x: 2, y: 5, width: 20, height: 15);
int right = rect.Right;
MessageBox.Show(right.ToString(), "Rectangle.Right"); //「22」
}
}
}
このプログラムでは、3つの異なる機能を次々と呼び出します。あくまで説明用のサンプルということです。
ポイントとなるのは JapaneseCalendar.GetEraメソッドとDirectoryInfo.CreationTimeプロパティとRectangle構造体のコンストラクターとRightプロパティです。
このサンプルを通して、非共有メンバーを呼び出し方や、使い方を学んでいきたいと思います。
JapaneseCalendarクラスは、日本の暦を表すクラスです。.NETのフレームワークには世界中の主だった暦を扱えるクラスがあり、日本の他に、イスラム歴(ヒジュラ)を扱うHijriCalendarクラスや、台湾の暦を扱うTaiwanCalendarクラスや韓国の暦を扱うKoreanCalendarクラスなどいろいろあります。
このサンプルではGetEraメソッドを使って 1920年6月20日の年号が明治なのか大正なのか昭和なのか平成なのか令和なのかを調べています。
//▼JapaneseCalendarクラスのGetEraメソッドの呼び出し
//GetEraメソッドの戻り値の意味。1:明治, 2:大正, 3:昭和, 4:平成, 5:令和
var calendar = new System.Globalization.JapaneseCalendar();
DateTime targetDate = new DateTime(1920, 6, 27);
int eraNumber = calendar.GetEra(targetDate);
MessageBox.Show(eraNumber.ToString(), "GetEra"); //「2」が表示されます。
GetEraメソッドは非静的メソッドなので JapaneseCalendar.GetEra のようには呼び出せず、インスタンスを使って呼び出す必要があります。
1行目では new を使って JanapeseCalendarクラスのコンストラクターを呼び出し、その結果生成されるインスタンスを変数 calendar に代入しています。
JapaneseCalendarクラスが属している System.Globalization名前空間は既定では省略可能ではないため、名前空間付きで明記しています。
変数 calendar の型はプログラム上は var を使って推論させています。JapaneseCalendarのコンストラクターの戻り値なので型は JapaneseCalendar型になります。
var を使わないで型を明示しても良いのですが、 System.Globalization.JapaneseCalendar calenar = new ... と書くと何だかプログラムが長くなってしまうので、コンストラクターの戻り値は var を使って型推論させるプログラマーが多数派のように感じます。
次の行で DateTime型の変数 targetDate に大正の日付 1920年6月27日 を代入しています。C#で日付や時刻を表現する場合は、フレームワークの DateTime構造体を使用します。日付と時刻については別途詳しく説明するつもりなのでここでは深入りしないでおきます。
次の行が GerEraメソッドの呼び出しです。非静的メソッドなのでインスタンス経由の呼び出しになっていますね。これがこのサンプルで私が言いたかった最大のポイントです。
GetEraメソッドは数字を返します。コメントに書いてあるように1が明治、2が大正…という具合です。1920年6月27日は大正なので 2 が返ってきます。なお、明治が始まったのは1868年9月8日です。GetEraメソッドはこれより前の日付には対応していません。日本でグレゴリオ暦が採用された1873年1月1日以前の日付は扱いが難しいのでご注意ください。
ポイント
DirectoryInfoクラスはフォルダー(ディレクトリー)に対するいろいろな情報の取得や操作を行うクラスです。
CreationTimeプロパティは、フォルダーの作成日時を表すプロパティです。値の取得だけではなく、値の書き換えもできてしまいます。非静的メソッドなのでインスタンス経由で呼び出す必要があります。
技術的には JapaneseCalendar.GetEra と同じなので難しいところはないと思います。GetEraはメソッドなのに対し、CreationTimeはプロパティなので = を使って値の読み書きをする点は異なります。
//▼DirectoryInfoクラスのCreationTimeプロパティの呼び出し
//フォルダーの作成日を実行時点から1年前に変更します。
//フォルダーのパスはみなさんの環境で存在するものに置き換えてください。
var folder = new DirectoryInfo(@"C:\temp\testfolder");
folder.CreationTime = DateTime.Now.AddYears(-1);
DirectoryInfoクラスが属する System.IO 名前空間は Windows フォーム アプリでは既定で省略可能なので記述する必要はありません。
new を使ってコンストラクターを呼び出しています。DirectoryInfoクラスのコンストラクターには対象のフォルダーのパスを引数で指定する必要があります。@ 付きの逐語的文字列を使っている理由は \ をエスケープシーケンスではなく普通の1文字として認識させるためです。もし @ がなければ \t はタブという意味になってしまいます。
コンストラクターの戻り値の型は var を使って推論させます。
DateTime.Now は 現在の日時を表します。たとえば、 2022年5月29日11時30分25秒にこのプログラムを実行すると、 DateTime.Nowは2022年5月29日11時30分25秒です。このような実行時点の日時のことを「システム日付」と表現することがあります。プログラムの世界では「日付」には時刻も含んでいます。
細かいので省略しましたが、DateTimeはもっと細かい100ナノ秒単位の値まで保持しています。が、コンピューターの時計はそこまで精密ではないので10ミリ秒以下の値はおおむね参考値程度です。
プログラムを見るとわかると思うのですが、Now は DateTime から直接呼び出されているのでの DateTimeの静的メンバーです。もっと言うと静的プロパティです。Nowの戻り値は システム日付を表すDateTimeのインスタンスです。このようにインスタンスを返すメンバーというものが存在するので、プログラム上は new が存在していなくてもインスタンスの取得が可能な場合もあります。
そのインスタンスから AddYearsメソッドを呼び出して、1年前の日付を表すインスタンスを生成し、folderの CreationTime に設定しています。
つまり、この1行は次のプログラムと等価です。
DateTime dtNow = DateTime.Now;
DateTime dt1YearsAgo = dtNow.AddYears(-1);
folder.CreationTime = dt1YearsAgo;
最後の例はクラスではなく構造体です。
Rectangle構造体は四角形を表します。
//▼Rectangle構造体のコンストラクターとRightプロパティの呼び出し
Rectangle rect = new Rectangle(x: 2, y: 5, width: 20, height: 15);
int right = rect.Right;
MessageBox.Show(right.ToString(), "Rectangle.Right"); //「22」
この例では、図のように左上の座標が(2, 5)で幅が20、高さが15の四角形を定義します。
Rectangle構造体自体には描画機能がなく、画面に何かが表示されるということはありません。数字の単位も決まっておらず、これをピクセル数とするのか、cmとするのかなどは描画や印刷などの処理を行うときに描画処理として決めることになります。
座標系はプログラムの世界では図のようにY軸が下方向を向いている座標系を使うことが多いです。この点は中学校の数学で出てくる座標系とは異なります。しかし、Rectangle構造体自体には座標系はないので学校数学の座標系をイメージしても構いません。
結局のところRectangle構造体は四角形の位置や大きさを表す数値の入れ物というだけで、それ以上の機能はないのです。
構造体についてはこれまでほとんど取り上げてきませんでした。基本的にはクラスと同じような存在ですが、何か機能を表現するクラスと違って「値の入れ物」を表現するとき構造体が採用されることが多いです。
クラスと大きく異なる点として、構造体のコンストラクターは自動的に呼び出されるため、自分で new を記述する必要はありません。
ちょっと小難しい説明をしましたが、簡単に言うと、new を使わなくても変数を宣言しただけでインスタンスになりますということです。ただし、わかりやすくするためにあえて new を記述したり、コンストラクターのオーバーロードを明示的に呼び出したいときに new を使う場合があります。
この例では、明示的に new を使ってコンストラクターのオーバーロードを呼び出しています。
この引数の指定の仕方はわざとちょっと変わった 「名前付き引数」という方法を使ってみました。
次のように単純に数字だけ並べてカンマで区切る通常の引数の指定方法も有効です。
Rectangle rect = new Rectangle(2, 5, 20, 15);
これを入力するときにヒントにこのように引数が表示されます。
四角形の左上のx座標、y座標、width(幅)、height(高さ)を順に入力するという意味です。
ヒントに表示されるx, y, width, height という引数の名前を使って引数を指定することも可能です。これが名前付き引数です。
引数の名前:値
という形式で指定することになります。名前と値の間には記号 : (コロン) を付けます。
この例ではこのようにしています。
Rectangle rect = new Rectangle(x: 2, y: 5, width: 20, height: 15);
名前付き引数の良いところは、プログラムを見ただけで引数の意味が分かるということです。英語がわかればですが…。
ただ単に数字が並んでいるとどの数字が何を意味しているのかぱっとみわかりにくいですが、名前付き引数で指定してれば大丈夫です。英語がわかれば…。
もう1つ、名前付き引数を使っている場合は、引数の順番を無視できます。
たとえば、このように書いても同じ意味です。
Rectangle rect = new Rectangle(width: 20, height: 15, x: 2, y: 5);
お好みならこのように書いても同じ意味です。
Rectangle rect = new Rectangle( x: 2,width: 20, y: 5, height: 15,);
名前付き引数はコンストラクターだけではなく、通常のメソッドなど引数が必要とされるすべての場所で使用することができます。もちろん構造体だけでなくクラスでも使用できます。
この例では次のように Rectangle構造体の Rightプロパティ(読み方:Right=ライト)の値を取得しています。
int right = rect.Right;
Rightは四角形の右端の座標を返します。
左側が x= 2 で幅(Width)が 20 なのだから、右端の座標は 22 です。
そういうわけで結果は22になります。
何気ないようですが、ここでフィールドとプロパティの違いがわかります。
フィールドもプロパティもクラスや構造体のメンバーで、よく似ています。何が違うのかよくわからないという人もいます。
フィールドは単なる値の入れ物です。変数と同じなのですが、クラスや構造体のメンバーとして存在している場合、これをフィールドと呼びます。
「フィールド」と「変数」は呼び方が違うだけなのですが、その違いに込められた人の「思い」というものに違いがあります。「思い」だけなので機能は同じです。フィールドという名前にに込められた「思い」とは、はクラスや構造体に化体して表現しようと意図された「モノ」のデータということなのですが、このあたりの感覚は当面気にしなくてよいと思います。
一方、プロパティは値の代入と参照ができるという点で変数に似ていますが、変数とは違って代入や参照を行ったタイミングで何かの処理が実行されることがあります。つまり、「プロパティ」と「変数」は名前が違うだけでなく機能が違うということです。
Rightプロパティを参照すると、Rectangle構造体のプログラムの中で計算処理が実行され、その結果を返します。Rectangle構造体では、Rightプロパティに相当する値は実際には持っておらず計算によって値を返しているというわけです。
プロパティが どのような処理をするかはプログラム次第であり、計算以外の処理を実行することも可能です。が、何かの処理が目的であればそれはメソッドであるべきなので、大多数のプロパティはRightプロパティのように計算した結果を返すはずです。第一、値を代入したり参照したりしただけで何か処理が実行されると予想外ですしわかりにくいです。でも、何かやむにやまれぬ事情があるか、行儀の悪いプログラマーが作るかして計算以外の処理を実行するプロパティもありえるので、このことは覚えておいた方がよいでしょう。
前回は非静的メンバーの呼び出し例を説明し、今回は非静的メンバーの呼び出し例を説明しました。やったことを簡単にまとめておきます。
静的メンバー | 非静的メンバー | |
---|---|---|
考え方 | 状態に関係ない値や機能。 たとえば、マウスの座標はUI部品の状態とは関係ないので静的メンバーでの表現が適している。 |
状態や状況によって変化する値や機能。 たとえば、UI部品の座標はUI部品ごとの配置によって変わるに出非静的メンバーでの表現が適している。 |
例 | ClipboardクラスのSetTextメソッド | StringBuilderクラスのAppendTextメソッド |
呼び出し方 | クラス名.メンバー名。 例 Clipboard.SetText("あいうえお") |
インスタンス経由。 例 var builder = new StringBuilder(); builder.AppendText("あいうえお") |
静的メンバーと非静的メンバーを区別する簡単な方法はVisual Studioの入力候補(インテリセンス)です。
入力候補にはその場で有効なメンバーが表示されるので Clipboard. のように クラス名. 入力して入力候補に表示されるメンバーは静的メンバーです。
インスタンスから入力候補で表示されるメンバーは非静的メンバーです。
一応、インスタンスから静的メンバーを呼び出すことも可能ですが、推奨されておらず入力候補にも表示されません。
引数と戻り値についてもいろいろ説明しました。
この他にもさまざまなことを説明しています。特に重要で覚えておいてほしいことはこんな感じです。
次の回では、問題集を使ってメンバーの呼び出し方を勉強の仕上げを行います。