はじめに
最近、C#の勉強を始めたので、忘れないようにこの記事でまとめようと思います。
間違いがあれば、ご指摘いただければ幸いです。
随時更新していきます。
※以後記載するプログラムはすべて自作になります。
クラス / フィールド / メソッド
クラスは作りたいものの設計図です。そして設計図は、フィールドとメソッドの2つの要素で構成されます。
フィールド
変数のこと。 public(アクセス修飾子) int(型) A(変数名)
の順で書く
メソッド
関数のこと。 public(アクセス修飾子) int(型) Calc(関数名)
の順で書く
※アクセス修飾子については後ほど記載
namespace Notepad{
class abc{ //==> クラス
public int A = 10; //==> フィールド
private int B = 10; //==> フィールド
public int Calc(){ //==> メソッド
return A*B;
}
}
}
インスタンス / コンストラクタ / 静的メンバ / Mainメソッド
インスタンス
クラスを使うためには、インスタンスというものを生成しなければなりません。
インスタンス生成は main.cs の (1.0) (※サンプルコードと番号が対応付いています)のように書きます。 a.Calc1();
と書くことによってsub.cs の (1.1) を呼び出すことができ、このプログラムでは 200 の値を返します。
コンストラクタ
コンストラクタとは、インスタンスを生成する際に初期化することです。
(2.0) でインスタンスを生成した際に、(2.2) の処理が実行され、変数 A が 30、変数 B が 50 に上書きされます。そのため、b.Calc1()
は 1500 の値を返します。
ちなみに、(2.0) で引数を指定しない場合、(2.1) の処理が実行されます。
静的メンバ
メソッドやフィールドに static と付け加えることでインスタンスを生成せずにメンバを利用できます。(3.0) のように クラス名.関数名
で関数を呼び出すことができます。
なお、static とついたメソッドは同じく static とついたフィールドしか使用できません。
※メンバ:メソッドとフィールドをまとめてメンバと言う
Mainメソッド
static void Main(string[] args)
のことを指します。(4.1)のように static とつけたメソッドを同一クラス内で定義すれば、(4.0)のようにインスタンスの定義なしに、メソッドを呼び出すことができます。
サンプルコード
namespace ConsoleApp
{
class Calc
{
public static int a = 10;
public static int b = 20;
//(4.1)
public static int Calc3()
{
return a * b;
}
static void Main(string[] args)
{
//(1.0) インスタンス
Calculate a = new Calculate();
a.Calc1();
//(2.0) コンストラクタ
Calculate b = new Calculate(30,50);
b.Calc1();
//(3.0) 静的メンバ
Calculate.Calc2();
//(4.0) Mainメソッド
Calc3();
}
}
}
namespace ConsoleApp
{
class Calculate
{
public int A = 10;
public int B = 20;
public static int sa = 10;
public static int sb = 20;
//(2.1)
public Calculate()
{
}
//(2.2)
public Calculate(int a, int b)
{
this.A = a;
this.B = b;
}
//(1.1) (2.3)
public int Calc1()
{
return A*B;
}
//(3.1)
public static int Calc2()
{
return sa * sb;
}
}
}
継承 / 抽象クラス / インターフェース
継承とはその他のクラスを利用できるようにすることです。
継承の方法は複数あります。以下のプログラムを用いて説明いたします。
PC_main.cs:一番最初に実行されるプログラム
PC_A.cs:AのパソコンのOS、CPU等の情報が記載されているプログラム
PC_B.cs:BのパソコンのOS、CPU等の情報が記載されているプログラム
PC.cs:AとBのパソコンの情報を取りまとめているプログラム
継承
継承は、その他のクラスを利用できるようにすることです。PC_A.cs と PC_B.cs を見ていただくと分かる通り、CPU の情報が同一です。そんな時に、継承を使うことで、同一の情報をひとまとめにしてくれます。
文法は PC_A.cs (2) を見ていただくと分かる通り、クラス名:引き継ぎたいクラス名
で継承できます。このプログラムでは、PC_A と PC_B が PC.cs の PC_inher を継承しています。
抽象クラス
抽象クラスとは、書くべき情報をまとめておいたものです。PC.cs (2) を見ていただくと分かる通り、各 PC で記載すべき情報が書かれています。今回は、A と B の 2 台の PC のみですが、今後、PC_C を書く場合に、どんな情報を記載すればよいか一目でわかります。抽象クラスで指定された情報をすべて書かなければ、エラーがでて実行ができなくなります。
文法は、PC.cs と PC_A.cs の (3) を見ていただくと分かる通り、継承元の関数には abstract、継承先の関数には override と記載する必要があります。なお、PC_B.cs の (3) のように抽象クラスで指定されていない関数も書き込むことができます。
インターフェース
インターフェースとは、各関数へのアクセスを制御するものです。各プログラムを簡略化した図1.を用いて説明します。
まず①で PC に必要なメソッドを書き込みます。次に②で各 PC に応じた必要なメソッドを取捨選択します。そうすると、③で PC_A.cs のインスタンスを生成した場合(正確には PC.cs クラス型のインスタンスを PC_A.cs クラス型にキャストする)に、②で選択したメソッドしか利用ができなくなります。PC_A.cs や PC_B.cs で使うメソッドを制約しているイメージだと思います。
_______________________________図1. プログラムの間略図
文法は、PC_A.cs PC_B.cs の (4) のような、制約をつけるプログラムにinterface 関数名
と記述し、PC.cs (4) のような大元のプログラムに、制約をつけるプログラムを継承させます。
PC_main.cs
namespace ConsoleApp
{
class PC_main
{
static void Main(string[] args)
{
// (1) 通常
PC_A pc_a = new PC_A();
pc_a.OS(); pc_a.CPU(); pc_a.Memory();
PC_B pc_b = new PC_B();
pc_b.OS(); pc_b.CPU(); pc_b.Memory(); pc_b.GPU();
// (2) 継承
PC_A_inher pc_a_inher = new PC_A_inher();
pc_a_inher.OS(); pc_a_inher.CPU(); pc_a_inher.Memory();
PC_B_inher pc_b_inher = new PC_B_inher();
pc_b_inher.OS(); pc_b_inher.CPU(); pc_b_inher.Memory(); pc_b_inher.GPU();
// (3) 抽象クラス
PC_A_abst pc_a_abst = new PC_A_abst();
pc_a_abst.OS(); pc_a_abst.CPU(); pc_a_abst.Memory();
PC_B_abst pc_b_abst = new PC_B_abst();
pc_b_abst.OS(); pc_b_abst.CPU(); pc_b_abst.Memory(); pc_b_abst.GPU();
// (4) インターフェース
PC_inter p = new PC_inter();
PC_A_inter pc_a_inter = (PC_A_inter)p;
pc_a_inter.OS("windows10"); pc_a_inter.CPU("intel core-i5"); pc_a_inter.Memory("8GB");
PC_B_inter pc_b_inter = (PC_B_inter)p;
pc_b_inter.OS("windows11"); pc_b_inter.CPU("intel core-i5"); pc_b_inter.Memory("16GB"); pc_b_inter.GPU("GeForce RTX 2060");
}
}
}
PC.cs
namespace ConsoleApp
{
//(2) 継承
class PC_inher
{
public void CPU() { Console.WriteLine("intel core-i5"); }
}
//(3) 抽象クラス
abstract class PC_abst
{
public abstract void OS();
public abstract void CPU();
public abstract void Memory();
}
//(4) インターフェース
class PC_inter:PC_A_inter,PC_B_inter
{
public void OS(string os) { Console.WriteLine(os); }
public void CPU(string cpu) { Console.WriteLine(cpu); }
public void Memory(string memory) { Console.WriteLine(memory); }
public void GPU(string gpu) { Console.WriteLine(gpu); }
}
}
PC_A.cs
namespace ConsoleApp
{
class PC_A { // (1) 通常
public void OS() { Console.WriteLine("windows10"); }
public void CPU() { Console.WriteLine("intel core-i5"); }
public void Memory() { Console.WriteLine("8GB"); }
}
class PC_A_inher:PC_inher { // (2) 継承
public void OS() { Console.WriteLine("windows10"); }
public void Memory() { Console.WriteLine("8GB"); }
}
class PC_A_abst:PC_abst { // (3) 抽象クラス
public override void OS() { Console.WriteLine("windows10"); }
public override void CPU() { Console.WriteLine("intel core-i5"); }
public override void Memory() { Console.WriteLine("8GB"); }
}
interface PC_A_inter{ // (4) インターフェース
void OS(string os);
void CPU(string cpu);
void Memory(string memory);
}
}
PC_B.cs
namespace ConsoleApp
{
class PC_B{ // (1) 通常
public void OS() { Console.WriteLine("windows11"); }
public void CPU() { Console.WriteLine("intel core-i5"); }
public void Memory() { Console.WriteLine("16GB"); }
public void GPU() { Console.WriteLine("GeForce RTX 2060"); }
}
class PC_B_inher:PC_inher { // (2) 継承
public void OS() { Console.WriteLine("windows11"); }
public void Memory() { Console.WriteLine("16GB"); }
public void GPU() { Console.WriteLine("GeForce RTX 2060"); }
}
class PC_B_abst:PC_abst { // (3) 抽象メソッド
public override void OS() { Console.WriteLine("windows11"); }
public override void CPU() { Console.WriteLine("intel core-i5"); }
public override void Memory() { Console.WriteLine("16GB"); }
public void GPU() { Console.WriteLine("GeForce RTX 2060"); }
}
interface PC_B_inter{ // (4) インターフェース
void OS(string os);
void CPU(string cpu);
void Memory(string memory);
void GPU(string gpu);
}
}
プロパティ / 自動実装プロパティ
プロパティ
他クラスからの呼び出し、書き込みを制御できるフィールドのこと
property.cs の classPC (1) に記載されている set はフィールドへの値の書き込み、get はフィールドの呼び出しをおこなっている。set、get どちらか一つにすることによって、読み込み専用、または呼び出し専用のフィールドにすることも可能である。
自動実装プロパティ
プロパティを簡略化したもの。property.cs の (2) の処理は、(1) と全く同一の処理である。
property.cs
namespace ConsoleApp
{
class PC_main
{
static void Main(string[] args)
{
//(1) プロパティ
PC pc = new PC();
pc.OS1 = "windows10";
Console.WriteLine(pc.OS1);
//(2) 自動実装プロパティ
pc.OS2 = "windows11";
Console.WriteLine(pc.OS2);
}
}
class PC
{
// (1) プロパティ
private string os1 = "";
public string OS1
{
set { os1 = value; }
get { return os1; }
}
// (2) 自動実装プロパティ
public string OS2 { set; get; }
}
}
アクセス修飾子
アクセスできる範囲を指定するもの。
public:アクセス制限なし。
private:アクセス制限あり。定義したクラス内でしか使用できない。
protected:継承したクラスのみアクセス可能
非同期処理(async,await)
並列処理のこと? なにか重い処理を動かしている最中でも、他の処理ができるようにする時用いるらしい。特にwindows formでよく使われるそう。
非同期処理をおこなう際は、メソッドに async とつけて、非同期にしたい処理に await をつける。このプログラムでは、同期処理ボタンを押した場合 5 秒間フォームが停止するが、非同期ボタンを押した場合、5 秒間停止しない。
↓詳しくは、こちら参照してください。
https://soft-rime.com/post-13199/
form1.cs
namespace qiita3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// 非同期処理ボタンをクリック
async private void button2_Click(object sender, EventArgs e)
{
await Task.Delay(5000);
}
// 同期ボタンをクリック
private void button1_Click(object sender, EventArgs e)
{
Thread.Sleep(5000);
}
}
}
_________________________________________図2. 実行結果
参考