- 投稿日:2020-11-04T23:49:25+09:00
C#基礎文法最速マスター【令和2年版】
最初に
本記事は「令和時代の基礎文法最速マスター Advent Calendar 2020」にてC#での基礎文法をまとめて記載した記事となります。
初心者の方の役に立てれば幸いです。まずは基本的なコードを確認してみましょう。
using System; namespace Test { public class HelloWorld { static void Main(string[] args) { string hello = "Hello 令和のC#!"; Console.WriteLine(hello); } } }構文
コメント
プログラムの処理に関係しない、プログラムに関する説明などを記載する場合には以下のように
//
もしくは/**/
を使用してソースコード内にコメントを埋め込みます。// 1文の場合 /* 複数行のコメントの場合、/**/で囲んだ文がコメントとなる。 */メソッド
static void Main(string[] args)プログラムはclass内の
Main
メソッドという特別なメソッドから始まります。このメソッドは、アプリケーション起動時に必ず最初に呼び出されます。
Main
メソッド内のWriteLine()
もメソッドであり、引数として渡した文字列を表示します。ユーザー側で定義する場合は基本的に以下のように書きます。
// アクセス修飾子 戻り値の型 関数名(引数の型 引数名) // void は結果として特に返すものはない時に使用する public void Attack() { // 何かしらの処理 } public bool IsDead() { // キャラが死んでいるかどうかを返却 } private void MoveForward(float AxisValue) { // 前進する処理 }クラス
public class HelloWorld { // メソッドや変数等 }
public
やprotected
を用いて「継承」や「多態性」という機能を使用することができます。classはcsファイル内に記述しますが、C#ではファイル名とクラス名は同一である必要性はありません。
また、1つのcsファイル内に複数の
class
を記述することも可能です。型と変数
string hello = "Hello 令和のC#!";予めプログラミング言語側で用意されている「組み込み型」には以下のような種類があります。
// ------------値型------------ // データ型名 変数名 // int(整数) int intNum = 2; // float(単精度浮動小数点) float floatNum = 1.234f; // double(倍精度浮動小数点) double doubleNum = 1.234; // bool(論理) // true か false 又は 1 か 0 です bool boolVal = true; // char(文字) // ローマ字一文字を``で囲みます char c = 'a'; // DateTime(日付) DateTime date; // ------------参照型------------ // String(文字列) // 文字列を""で囲みます String str = "hoge"; // 配列型 // 詳細は後述 int[] array;また、先ほどのような自分で作成した
class
を基にした変数も使用可能です。
これを「ユーザー定義型」と呼びます。public class HelloWorld { public string Say() { return "Welcome C# World!"; } } public class Hoge { HelloWorld hello = new HelloWorld(); string str = hello.Say(); }四則演算
// num = 2 int num = 1 + 1; // num2 = 0 int num2 = 1 - 1; // num3 = 3 int num3 = 1 * 3; // 小数点以下切り捨て // num4 = 0 int num4 = 1 / 2; // floatなので小数点が扱える // num5 = 0.5 float num5 = 1 / 2; // 余りの数の求め方 // num6 = 1 int num6 = 10 % 3; // 複合代入演算子 // num = 2 num6 += 1; // num = 1 num6 -= 1;インクリメント/デクリメント
++
という、変数に対して1
を足す専用の演算子がインクリメント演算子
というものです。主にループ処理などで使用されます。
インクリメント演算子
には前置インクリメント
と後置インクリメント
があります。違いは処理にする変数にて、1を足した後の結果を使用するか、足す前の値を使用するかで違いがあります。
using System; class Test { static void Main() { int i = 10; int k = 10; // 11が表示される Console.WriteLine(++i); // 10が表示される Console.WriteLine(k++); // 以降は k の値は11となっている } }また、変数に対して
1
を足す`インクリメント演算子
に対して、変数に対して1
を引くデクリメント演算子
というのも存在しています。使い方は
インクリメント演算子
と変わりません。using System; class Test { static void Main() { int i = 10; int k = 10; // 9が表示される Console.WriteLine(--i); // 10が表示される Console.WriteLine(k--); // 以降は k の値は9となっている } }アクセス修飾子
public class HelloWorld { // メソッドや変数等 }アクセス修飾子は外部からその
class
やメソッド、変数を見たときに、使用できるか否かを決めます。public class Character { // 誰からも見えるし、誰でも使える public GetHP(); public GetName(); // このCharacterクラスの内部処理内でしか見えないし、使えない private void SetRotation(); }他にも
protected
がありますが、こちらは継承の機能を使用する際に使います。名前空間
namespace Test { // HelloWorldクラス等 }名前空間(
namespace
)とは、同じ名前が存在する(名前衝突)現象を防ぐ役割を持ちます。例えば以下のように書くと名前の重複でエラーが起きます。
namespace ClassA { public class Sato { // なにかしらの処理 } public class Sato { // error! } }しかし
namespace
を使うことによって名前衝突を防ぐことができます。namespace ClassA { public class Sato { public void Hello() { Console.WriteLine("My name is Sato! My class is A!"); } } } namespace ClassB { public class Sato { Console.WriteLine("My name is Sato! My class is B!"); } }呼び出す時は名前空間付きで呼び出しましょう。
これを「完全修飾名」と言います。
namespace Test { public class HelloWorld { static void Main(string[] args) { ClassA.Sato sato = new ClassA.Sato(); sato.Hello(); } } }
using
というキーワードを使用することで、修飾名を省略して書くことができます。この機能を
usingディレクティブ
と呼びます。using ClassA; namespace Test { public class HelloWorld { static void Main(string[] args) { Sato sato = new Sato(); sato.Hello(); } } }配列
// 型名[] 変数名; string[] array;配列の初期化には様々な方法があります。
// 普通の配列 // 変数 = new 型名[配列の長さ] int array = new int[3]; // 配列の要素ごとに値を代入 array[0] = 5; array[1] = 10; // 初期データを指定 int array2 = new int[] { 0, 5, 10 }; string[] cats = {"黒猫", "三毛猫", "ぶち", "はちわれ"}; // ジャグ配列での初期化 int[][] jagged = new int[][] { new[] {1, 2, 3}, new[] {4, 5, 6, 7} }; // 四角配列での初期化 int[,] grid = new int[,] { {1, 1, 1}, {2, 2, 2}, {3, 3, 3} };if
条件分岐の処理を行う際に使用する構文です。
bool isDead = Hero.IsDead(); // もし勇者が死んでいたら // if(isDead)でも可 if(isDead == true) { // Gameover処理 } else { // 生きていたらClear処理 // else if(isDead != true) や // else if(!isDead) とも書ける }switchとenum
こちらも条件分岐などを行う際に使用すると便利な構文です。
enumとは
列挙型
と呼ばれる機能で、特定の値のみを取るようなものに対して使用します。enum DayOfWeek { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }
switch
文は指定した変数の値によって処理を切り替えます。DayOfWeek day = DayOfWeek.Monday; switch(day) { case DayOfWeek.Sunday: // おやすむ処理 // breakが書かれることで処理を抜けます break; case DayOfWeek.Monday: case DayOfWeek.Tuesday: case DayOfWeek.Wednesday: case DayOfWeek.Thursday: case DayOfWeek.Friday: // 頑張ってお仕事するにゃんねぇの処理 // caseにbreakを入れない場合は次のcaseの処理も続けて実行されます break; default: // defaultは変数の値がcaseで定義されている中のどれとも異なる場合に実行されます // 今回はSaturdayが対象です。 break; }C#7.0からは以下のように型による分岐もできます。
switch (obj) { case int n: // 整数だった場合の処理 break; case string s: // 文字列だった場合の処理 break; case bool b: // boolだった場合の処理 break; default: // その他の場合の処理 break; }whileとfor
これはどちらもループ処理を行う際に使用する構文です。
まずはwhileから見てみましょう。
while(条件式) { // ループ処理 }例えば条件式の部分に
true
と書くとどこかでbreak
を書かなくては無限ループとなります。int i = 0; while(i < 10) { ++i; // 何か処理 if(i == 5) { // while文から抜ける break; } }次にfor文です。
こちらは、ループ処理に使用する変数の宣言・初期化と条件式、変数の値の更新をセットにして書くことができます。
for(初期化式; 条件式; 変数の更新式) { // ループ処理 }例えば、以下のように配列の要素を参照するときなどに使用できます。
int[] array = { 0, 5, 10 }; for(int i = 0; i < array.Length; i++) { if(array[i] == 0) { // continueを書くとここでループ処理が中断され、変数の更新後ループ処理の頭から再度開始します continue; } array[i] += 10; } // arrayの中身は 0, 15, 20となるforeach
foreach
を使うと、配列の各要素にアクセスして処理を行うのが楽になります。int[] array = { 0, 5, 10 }; // foreach(変数宣言 in ループ処理したい配列) foreach (int num in array) { num += 10; }例外処理
例外を投げる場合には
throw
を使用します。throw new Exception("not found!");また、その例外を処理するには
try ~ catch
を使用します。try { // 例外が発生する可能性のある処理 } catch(Exception e) { // 例外に対応した処理 }最後に
更に詳しくC#について知りたい方は以下のスライドを見てみてください~
https://speakerdeck.com/rossam/shi-te-wakaru-c-number-7-dot-1madefalseyan-yu-ji-neng
また、私の心の中で密かに師匠と崇めている岩永さんの技術ブログも非常におすすめです。
それでは良きC#ライフを!
- 投稿日:2020-11-04T22:12:12+09:00
privateの想像と違う(?)動作のお話
初書:2020/11/4
php:7.4.10前書き
オブジェクトを使う際にほぼ間違いなく使うprivate。
今回は(個人的に)意外な性質を見つけたのでメモ。コード
先にコードを提示
class tes{ private int $a = 1232; private function fc():int{ return $this->a; } public function func(tes $val) : int { return $val->fc() + 158; } } $a = new tes(); $b = new tes(); var_dump($b->func($a));数字・関数名変数名は適当。
いや今気がついたけどこのコードだとfcの定義している意味が完全に無いじゃん。
まぁ支障はないので一旦放置。簡単にコードの説明をしておくと、private変数
$a
を用意しておき、fc
関数で取得可能。
またfunc
関数では、tesクラスのインスタンスを引数とし、fc
関数と158を足した値を戻す。
そして2つのインスタンスを生成し、片方のインスタンスを引数にもう片方のfunc
を呼ぶというもの。さて、上記コードを実行してみるとどうなるか。
php > var_dump($b->func($a)); int(1390)普通に実行できる。
何が言いたいのか
つまり、privateな関数や変数1であっても、同じクラス内から呼び出す分には別のインスタンスであっても呼び出すことが可能である。(初知り)
javascriptでも試してみる。
class tes{ #a = 1232; #fc(){ return this.#a; } func(val){ return val.#fc() + 158; } } a = new tes(); b = new tes(); console.log(b.func(a));(ちなみに
#
から始まるのをフラグメント演算子というらしいのだが、いつから実装されてるのか不明。2)さて、結果はどうなったのか。ちなみにページを用意するのが面倒だったので、コンソールに投げて実行した。
safari
ver 14.0
SyntaxError: Invalid character: '#'そもそもフラグメント演算子に対応していない
chrome
ver 86.0
1390phpと同様の結果に。
Firefox
ver 82.0
Uncaught SyntaxError: private fields are not currently supported認識はするものの対応自体はしていない模様
結果
phpと同じと認識してもいいと思われる
C#でも試す。
C#というよりunity。
using UnityEngine; public class test2 : MonoBehaviour{ void Start(){ var a = new tes(); var b = new tes(); print(b.func(a)); } } class tes{ private int a = 1232; private int fc(){ return a; } public int func(tes val){ return val.fc() + 158; } }普通に1390と出た。
結論
もしかして単純に無知を晒した投稿なのでは?(今更。でも書いてしまった)
「privateは1カプセル毎に個別で持つもの、外部からは一切アクセスできない」という認識があったので少し意外な処理だった。
- 投稿日:2020-11-04T18:47:01+09:00
UnityでSliderを使ってCubeを回したい
やること
タイトル通り、UnityのSliderを使ってCubeを回します。
オブジェクト間の値わたしについて、Sliderを例に理解していきます。
自分が全忘却した時の備えとして、工程を全メモします。
たぶんUnityをインストールしただけでほとんど使い方がわからないという人でもできます。素材の準備
キャンバス、スライダー、キューブ、キューブ用スクリプトの4つを準備します。すべてデフォルト機能のものです。
① Canvasを準備
スライダーを設置するためのCanvasを準備します。Canvasはカメラの前に置くレイヤーのような画面で、ゲームのスコアなどを表示する面です。
Hierarchyウィンドウの何もないところで「右クリック」→「UI」→「Canvas」
Canvasを設定すると、EventSystemというオブジェクトも同時に生成されます。
② Sliderを準備
Sliderはドラックで数値を入力できる長いスイッチです。
これをCanvasの上に設置します。Hierarchyウィンドウの「Canvas」の上で「右クリック」→「UI」→「Slider」
設置が終わったらシーンビュー(メインウィンドウ)の上のタブを「Scene」ビューから「Game」ビューに切り替えると、画面にスライダーが設置されていることがわかります。
(GameビューはUnityの再生時に見えるカメラ目線で、Sceneビューは作業用の目線になります。)③ Cubeを準備
スライダーを使って回転させるCubeを置きます。
Hierarchyウィンドウの何もないところで「右クリック」→「3D Object」→「Cube」
④ Scriptを準備
ProjectウィンドウのAssetsの中の何もないところで「右クリック」→「Create」→「C# Script」を選択し、ファイル名を「SliderDemo」とします。
これで今回使う素材の準備が整いました。
UnityのPublicを理解する
Unityは各オブジェクトに紐づく変数や関数を他のオブジェクトとやりとりしたり、右のInspectorウィンドウに項目としてその値を表示し、書き換えもできるようになっています。
そこがUnityの便利なところなのですが、変数にその機能を持たせるにはPublicというアクセス権を設定する必要があります。という話。大事なのはそこだけです。仕込み
① CubeにアタッチするC#スクリプトを書く
SliderDemoのファイルを開くと、スクリプトをUnityで使えるようにするための雛形がすでに記述されています。
MonoBehaviourというUnityでしか見ない単語があり気になりますが、Unityで扱えるようにするための標準セットを継承するためのもの、ぐらいに考えておけばよさそうです。
また、Unityのスクリプトには「ファイル名とスクリプト内のclass名を必ず同じにする」という大事なルールがあるので注意が必要です。内容を追記し、下記のように改めます。
SliderDemousing UnityEngine; public class SliderDemo : MonoBehaviour //Unity標準クラスを継承 { //スライダーの値を「取得する」ためのパブリック変数を定義する関数 //取得した値のCubeの回転への反映もここで行います。 public void SliderDemo_CubeRot(float newValue) { // キューブを回転させるための変数を宣言 // Vector3変数は3つの値を格納できる型 // その変数に現在のオイラー角xyzを代入 // thisはこのスクリプトをアタッチしたGameObjectを表す Vector3 rot = this.transform.localEulerAngles; // 縦軸のy成分を代入 rot.y = newValue; // 新しい数値をキューブの角度に代入 this.transform.localEulerAngles = rot; } // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } }Cubeを回転させるためのTransformのところは今回はあまり気にしないでください。
void Start()やvoid Update()はカラのままで大丈夫です。② スライダーの設定をする
HierarchyウィンドウのSliderを選択すると、右のInspectorに設定画面が出ます。
一番下の方にMin Value、Max Valueという項目があるので、ここにスライダで操作したい回転度数の範囲として-180と180を入力しておきます。
ちなみにその下にあるWholo Numbersというチェックボックスですが、これをチェックするとValueの値を整数に制限できるそうです。仕上げ
オブジェクトやコンポーネントをアタッチして関連づける
オブジェクト(GameObject)というのはUnityの要素の単位で、キャラクターはもちろん、マシンガンの球、光源、ビュー用のカメラまでゲームを構成するあらゆる物体の基本となるものです。またコンポーネントというのはオブジェクトに内包される構成要素で、形、色、衝突判定やスクリプトなどが定義されます。
衝突判定はUnityの物理世界の中で最初から相互に関連するようになっていますが、独自に設定した変数や関数についてはオブジェクト同士で紐付けないと作用がしません。
ということで、① スクリプトをCubeにアタッチする
Assets内のSliderDemoのスクリプトファイルを、HierarchyウィンドウのCubeにドラッグ&
ドロップでアタッチします。しっかり重ねるとブルーにハイライトするので、その時にドラッグします。(ちゃんと重ねないとグレーのハイライトとなり、その状態ではアタッチされません)
Cubeのインスペクターウィンドウに「SliderDemo(Script)」という項目が追加されていれば成功です。② スライダーにCubeをアタッチする
ここがミソです。Sliderの値(Value)をどう取り出すかという話。
SliderのInspectorの下にある「On Value Changed(Single)」という項目を使います。ここでプラスを押すと、Valueの渡し先を設定できるようになります。項目の説明です。
まず左上のプルダウンメニューの「OFF/Editor and Runtime/Runtime Only」の選択ですが、Runtime Onlyを選んでおけば大丈夫です。(Editor and Runtimeを選べば、再生中以外でもスライダーの値が反映されるようになるようです。)次に、その下のボックスにオブジェクトをアタッチします。
今回はCube(Hierarchyウィンドウ内)をこのボックスにドラック&ドロップします。すると右側のプルダウンメニューからSliderDemoの項目を選べるようになります。いま関連づけたCubeにはSliderDemoのスクリプトがアタッチされており、その内容である関数が選べるようになっているというわけです。
さっそく「SliderDemo」→「SliderDemo_CubeRot」を選択します。この設定をすることでスライダーで設定したValueの値(-180~180)が独自に設定した関数「SliderDemo_CubeRot」に渡されるようになりました。
これで準備は完了です。
完成・実行
画面上部の三角ボタンからプログラムを実行します。
スライダーの操作に連携して、キューブが横に回転してくれます。
- 投稿日:2020-11-04T18:37:22+09:00
【C#】リフレクションで静的プロパティにアクセスするのはめんどくさい
はじめに
リフレクションを利用して静的プロパティにアクセスしたいときってありますよね?
(public
ではないプロパティを触りたいときなど)
ググるとやり方はいくらでも出てきますが,それにもかかわらず実際に書いてみると躓いてしまったので,記事として残しておこうと思います。やり方
ダラダラ書いてもしょうがないので例を示します。
ここでは,別アセンブリ内の静的クラスQiita.MyClass
に定義されているProp
の値を取得します。
当然ですが,Qiita.MyClass
が定義されているアセンブリが参照に追加されている必要があります。// using System; // using System.Reflection; // 別アセンブリ内のクラスは`Type.GetType`では取得できないので,`Assembly.GetType`を利用する。 Type MyClass; foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) // 読み込まれているアセンブリを取得 { var T = asm.GetType("Qiita.MyClass"); // 目的の型を取得しようとしてみる。 if (T != null) // 取得できなかったら`null`になる。 { MyClass = T; break; } } // StaticとNonPublicを両方指定しないといけない。 var info = MyClass.GetProperty("Prop", BindingFlags.Static | BindingFlags.NonPublic); // ここでも`BindingFlags.Static`が必要。 dynamic val = info.GetValue(MyClass, BindingFlags.Static, null, null, null); // 取得した`val`で何かする最後の
PropertyInfo.GetValue
の呼び出し時にBindingFlags.Static
を渡さないとArgumentException
になってしまいます。
これがわからなかったので時間を溶かしてしまいました。
調べても書いてなかったんだもん
PropertyInfo.GetValue
の戻り値はobject
ですが,dynamic
で受けると適当な型として扱えます。怖いですが……。まとめ
public
ではないということには理由があるので,リフレクションで強引にアクセスしようとするのはやめましょう。
(パフォーマンス的にもよろしくない)
- 投稿日:2020-11-04T14:35:58+09:00
C# / WPFで数字入力欄の値をEnter押下時に指定桁数でゼロ埋めする
前説
'0001' のような入力を行うTextBoxで、1を入力すると先頭部分をゼロ埋めするようにしたかった。
こちらの記事を参考に、WPFな業務アプリでキー操作によるフォーカス移動などのビヘイビアを使っていた。
とりえあず↑を参考に動作できたので、忘れないうちにメモ。ビヘイビアの定義
上記サイトのようにBehaviorsフォルダに以下のようなファイルを追加(元サイトのBehaviorBase.csを継承)。
呼び出すxamlファイルのTextboxに入れる。TextBoxZeroPadding.csusing System.Diagnostics; using System.Windows.Controls; using System.Windows.Input; /* * XAML内で使うビヘイビア * * Enter押下時、TextBox内の数字をゼロ埋めする * */ namespace GyomuApp.Behaviors { /// <summary> /// TextBox用ビヘイビア /// MaxLengthに沿ってゼロ埋めする /// </summary> public class TextBoxZeroPadding : BehaviorBase<TextBox> { /// <summary> /// イベント登録 /// </summary> protected override void OnAttached() { base.OnAttached(); // TextBoxのキーダウンイベントにOnKeyDownを登録 AssociatedObject.PreviewKeyDown += OnPreviewKeyDown; } /// <summary> /// イベント解除 /// </summary> protected override void OnDetaching() { base.OnDetaching(); } /// <summary> /// キー押下イベント /// </summary> /// <param name="sender">TextBox</param> /// <param name="e">キーイベントデータ</param> private void OnPreviewKeyDown(object sender, KeyEventArgs e) { if (sender is TextBox textBox) { switch (e.Key) { case Key.Enter: if (textBox.Text == "") break; var zeroForm = new string('0', textBox.MaxLength); var format = "{0:" + zeroForm + "}"; textBox.Text = string.Format(format, short.Parse(textBox.Text)); break; } } } } }XAMLファイルは抜粋で書くと↓
<!-- 個数 000 --> <TextBox Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Right" TextWrapping="Wrap" TextAlignment="Center" FontSize="14" VerticalAlignment="Center" Margin="0,0 0 0" Width="290" MaxLength="3" Text="{Binding EntryQty, Mode=TwoWay}" > <behaviors:Interaction.Behaviors> <b:TextBoxIntegerOnly /> <b:TextBoxMoveFocus /> <b:TextBoxZeroPadding /><!-- ← これ --> </behaviors:Interaction.Behaviors> </TextBox>これで、指定TextBox内で数字を入れてEnterキーをおすと、ゼロ埋めされる。
フォーカス移動のEnterキービヘイビアTextBoxMoveFocusも同時に指定しているが、問題なく動くようだ。逆に数値入力のみのビヘイビアと同時指定する前提なので、こちらがない場合はエラーが出ると思われる。
- 投稿日:2020-11-04T09:58:37+09:00
C#の様々なクラスについて
著者:桂素偉 翻訳者:欧Lily もし誤りがございましたらご指摘いただければ幸いです
本記事は初心者向けの基礎的な知識です!!!
普通クラス 静的クラス 抽象クラス シールクラス 部分クラス 修飾子 無 static abstract sealed partial コントラストが呼び出されるタイミング newキーワードでインスタンスを生成する際 任意の内部メンバーが呼ばれる際 派生クラス newキーワードでインスタンスを生成する際 newキーワードでインスタンスを生成する際 newキーワードでインスタンスを生成する際 メンバー フィールド、プロパティ、メソッド、イベント、インデクサ、演算子のオーバーロード、ユーザー定義型 静的フィード、 静的プロパティ、静的メソッド、静的イベント、ユーザー定義型 普通クラスの すべてのメンバー、抽象プロパティ、抽象メソッド 抽象イベント 抽象インデクサ 普通クラス すべての メンバー 普通クラス すべての メンバー 特徴 インスタンスを生成できる。継承できる クラス名.メンバー名でアクセスできる 派生クラスでインスタンス化 継承の禁止 クラスの分割定義 /// <summary> /// 普通クラス /// </summary> public class CommonClass { /// <summary> /// ユーザー定義enum型 /// </summary> enum MyEnum { enum1, enum2 } /// <summary> /// ユーザー定義delegate型 /// </summary> public delegate void MyDeleaget(); /// <summary> /// コンストラクタ /// </summary> public CommonClass() { _arr = new double[10]; } /// <summary> /// フィールド /// </summary> private string _myField; /// <summary> /// プロパティ /// </summary> public string MyProperty { get; set; } /// <summary> /// メソッド /// </summary> public void MyMethod() { } /// <summary> /// イベント /// </summary> public event MyDeleaget MyEvent; /// <summary> /// 演算子オーバーロード /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static CommonClass operator +(CommonClass a, CommonClass b) { return new CommonClass() { MyProperty = a.MyProperty + b.MyProperty }; } /// <summary> /// インデクサコレクション /// </summary> double[] _arr; /// <summary> /// インデクサ /// </summary> /// <param name="index"></param> /// <returns></returns> public double this[int index] { get { return _arr[index]; } set { _arr[index] = value; } } } /// <summary> /// 静的クラス /// </summary> public static class StaticClass { /// <summary> /// 静的コンストラクタ /// </summary> static StaticClass() { Console.WriteLine("静的コンストラクタ"); } /// <summary> /// 静的メソッド /// </summary> public static void StaticMethod() { Console.WriteLine("静的クラスの静的メソッド"); } /// <summary> /// 静的プロパティ /// </summary> public static string StaticProperty { get; set; } /// <summary> /// ユーザー定義delegate型 /// </summary> public delegate void MyDeleaget(); /// <summary> /// フィールド /// </summary> private static string _myField; /// <summary> /// イベント /// </summary> public static event MyDeleaget MyEvent; } /// <summary> /// 抽象クラス /// </summary> public abstract class AbstractClass { public AbstractClass() { Console.WriteLine("抽象クラスのコンストラクタ"); } /// <summary> /// ユーザー定義delegate型 /// </summary> public delegate void MyDeleaget(); /// <summary> /// プロパティ /// </summary> public string MyProperty { get; set; } /// <summary> /// メソッド /// </summary> public abstract void MyMethod(); /// <summary> /// イベント /// </summary> public abstract event MyDeleaget MyEvent; /// <summary> /// インデクサ /// </summary> /// <param name="index"></param> /// <returns></returns> public abstract double this[int index] { get; set; } } /// <summary> /// シールクラス /// </summary> public sealed class SealedClass { /// <summary> /// コンストラクタ /// </summary> public SealedClass() { Console.WriteLine("シールクラスコンストラクタ"); } /// <summary> /// ユーザー定義delegate型 /// </summary> public delegate void MyDeleaget(); /// <summary> /// フィールド /// </summary> private string _myField; /// <summary> /// プロパティ /// </summary> public string MyProperty { get; set; } /// <summary> /// メソッド /// </summary> public void MyMethod() { } /// <summary> /// イベント /// </summary> public event MyDeleaget MyEvent; /// <summary> /// オペレーターのオーバーロード /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static SealedClass operator +(SealedClass a, SealedClass b) { return new SealedClass() { MyProperty = a.MyProperty + b.MyProperty }; } /// <summary> /// インデクサコレクション /// </summary> double[] _arr; /// <summary> /// インデクサ /// </summary> /// <param name="index"></param> /// <returns></returns> public double this[int index] { get { return _arr[index]; } set { _arr[index] = value; } } } /// <summary> /// 部分クラス1 /// </summary> public partial class PartialClass { public PartialClass() { Console.WriteLine("部分クラスコンストラクタ"); } /// <summary> /// ユーザー定義delegate型 /// </summary> public delegate void MyDeleaget(); /// <summary> /// フィールド /// </summary> private string _myField; /// <summary> /// プロパティ /// </summary> public string MyProperty { get; set; } /// <summary> /// メソッド /// </summary> public void MyMethod() { } /// <summary> /// オペレーターオーバーロード /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static PartialClass operator +(PartialClass a, PartialClass b) { return new PartialClass() { MyProperty = a.MyProperty + b.MyProperty }; } /// <summary> /// インデクサコレクション /// </summary> double[] _arr; } /// <summary> /// 部分クラス1 /// </summary> public partial class PartialClass { /// <summary> /// イベント /// </summary> public event MyDeleaget MyEvent; /// <summary> /// インデクサ /// </summary> /// <param name="index"></param> /// <returns></returns> public double this[int index] { get { return _arr[index]; } set { _arr[index] = value; } } }