ホームに戻る
 C#メモ

0、はじめに

C#はJavaに似たプログラム言語です。
Javaとは仕様の違いがあるので、特徴的なところをまとめてみます。
C++ほど奇々怪々ではありませんがJavaほどすっきりしません。
Javaと違ってC#では仮想マシンをVMと呼びません。
.NETフレームワークのCLR(Common Language Runtime)と呼ぶそうです。

1、例文

// Test.cs (拡張子は .cs です。)

// using System;  // これで System. を省略できる。

class Test{
  private int a = 1; // private などはデータ型の前に 初期化もここで

  static int Main(string[] args){  // C#における main です。
    Test t = new Test();  // C++と違いポインタ的表現はありません。
    System.Console.Write("Te");  // System は namespace。
    System.Console.WriteLine("st" + t.a);
    System.Console.ReadKey();
    // 仮想マシンが解放するので delete はありません。
    return 0;
  }
}

実行結果

Test1

2、データ型

object型、bool型、string型

などがあります。

ポインタも使える。

列挙型は、

enum NUM : int {A = 0, B, C}

とし、

(int)NUM.A

などとしてアクセスします。

3、const

データ型は const をつけると数値が変更できないのはC++と同じ。
コンストラクタ内でのみ変更ができる readonly というのもある。

class Test{
  public const string str1 = "test1";  // static はつけても一緒なのでつけない
  public static readonly string str2;  // static をつけるかどうかで挙動が変わる

  static Test(){
    //str1 = "test1";  // 不適切
    str2 = "test2";  // 可能
  }

  static void Main() {
    //str2 = "test3";  // 不適切
  }
}

4、配列

class Test{
  static void Main(){
    // int[,] p = new p[3, 2];  // 初期化しない場合

    int[,] p = { // [] → [,] → [,,] と次元は増やせる。
      {0 , 1},
      {2 , 3},
      {5 , 7}
    };

    for (int i = 0; i < p.GetLength(0); i++){  // GetLength で最大数を得る
      for (int j = 0; j < p.GetLength(1); j++){
        System.Console.WriteLine(p[i, j]);
      }
    }
  }
}

実行結果

0
1
2
3
5
7

また、次のような定義も可能。

int[][] p = new int[3][];
p[0] = new int[] {0, 1};
p[1] = new int[] {2, 3};
p[2] = new int[] {5, 7};

5、構造体

構造体はクラスと違いデータをヒープでなくスタックに置く。
CやC++のものとはまったく別物なので、気を抜くと痛い目にあいそう。

public struct point{
  public int x, y;  // ここで = 0 などとして初期化できない。
  public point(int x, int y){this.x = x; this.y = y;}
  public void print(){
    System.Console.WriteLine(x + ":" + y);
  }
}

class Test{
  static void Main(string[] args){
    point p1 = new point();  // x や y の初期化は 0 で行われる。
    point p2;
    point p3 = new point(50, 50);
    p1.print();
    //p2.print();  // 不適切
    p2.x = 20;  // 値を入れないとエラー
    p2.y = 30;  // 値を入れないとエラー
    System.Console.WriteLine("{0}:{1}", p2.x, p2.y);
    p3.print();
    System.Console.ReadKey();
  }
}

実行結果

0:0
20:30
50:50

6、算術演算、制御文

算術演算や制御文には大きな違いは無い。

7、internal

コンパイル単位の名前参照を許可し、
リンク単位では外部に名前を参照させない。

class A{
  internal void print(){
    System.Console.WriteLine("test");
  }
}

8、動的引数

動的に引数の個数を変えることができます。

class Test {
  public static void print(params int[] p) {
    for(int i = 0; i < p.Length; i++){
      System.Console.Write(p[i]);
    }
    System.Console.WriteLine("");
  }
  static void Main(){
    print(0);
    print(1, 2, 3);
  }
}

実行結果

0
123

9、静的コンストラクタ

C#にもコンストラクタは存在しますが、
C#には static なコンストラクタが認められます。
new などでインスタンスを与える必要はありません。

class St{
  static string str = "test";
  static St(){}
  public static void print(){
    System.Console.WriteLine(str);
  }
}

class Test_st{
  static void Main() {
    St.print();
  }
}

実行結果

test

10、参照

引数に参照が使えます。
ref と out の使い分けがある点に注意。

class Test{
  static void Main() {
    int x = 0 , y;
    getXY(ref x , out y); // 初期化されているときは ref されていないと out
    System.Console.WriteLine(x + ":" + y);
  }
  static void getXY(ref int x , out int y){
    x = 50;
    y = 100;
  }
}

実行結果

50:100

11、継承

C#では多重継承は禁止されています。
また、メンバの隠蔽は new で明示しないと警告がでます。

class A{
  public int num = 0;
  public A(int num){this.num = num;}
}

class B : A{  // public な継承しかありません
  new public int num = 2;  // あえて A の num を隠蔽するので new をつける
  public B() : base(1){}
  public void print(){
    System.Console.WriteLine(base.num + ":" + num);  // 親クラスには base でアクセス
  }
  static void Main(){
    B b = new B();
    b.print();
  }
}

実行結果

1:2

12、仮想関数

C++同様に仮想関数は存在します。
C#では仮想関数をオーバーライドする場合 override を書かないと警告がでます。

class A{
  public void f(){
    System.Console.WriteLine("A:f");
  }
  public virtual void vf(){
    System.Console.WriteLine("A:vf");
  }
}

class B : A{
  new public void f(){
    System.Console.WriteLine("B:f");
  }
  public override void vf(){ // override を書くこと
    System.Console.WriteLine("B:vf");
  }
}

class Test{
  static void Main(){
    A a1 = new A();
    A a2 = new B();
    //B b1 = new A(); // 不適切
    B b2 = new B();

    a1.f();
    a1.vf();
    a2.f();
    a2.vf(); // これは B の vf を呼ぶ
    b2.f();
    b2.vf();
  }
}

実行結果

A:f
A:vf
A:f
B:vf
B:f
B:vf

13、抽象クラス

あえてインスタンスを作れないクラスを抽象クラスと呼ぶ。

abstract class A{
  public void f(){
    System.Console.WriteLine("A:f");
  }
  public abstract void af(); // abstract 関数は中身を定義できない。
}

class B : A{
  new public void f(){
    System.Console.WriteLine("B:f");
  }
  public override void af(){ // override を書くこと
    System.Console.WriteLine("B:af");
  }
}

class Test{
  static void Main(){
    //A a1 = new A(); // 不適切
    A a2 = new B();
    //B b1 = new A(); // 不適切
    B b2 = new B();

    a2.f();
    a2.af(); // これは B の vf を呼ぶ
    b2.f();
    b2.af();
  }
}

実行結果

A:f
B:af
B:f
B:af

14、シールドクラス

あえて継承させたくないクラスに sealed をつけます。

class の前に sealed をつけると継承するとエラーになります。
また、override した関数をこれ以上オーバーライドさせないように、
関数に対しても sealed override をつけることがあります。

15、インターフェイス

考え方はJavaのものと同じです。
interface C : A, B{} のように結合することも可能です。

interface Print{
  void print();
}

class A : Print{
  public void print(){
    System.Console.WriteLine("A");
  }
}

class B : Print{
  public void print(){
    System.Console.WriteLine("B");
  }
}

class Test{
  static void Main(){
    Print pa = new A();
    Print pb = new B();

    pa.print();
    pb.print();

    System.Console.ReadKey();

    return 0;
  }
}

実行結果

A
B

16、例外

例外は try、throw、catch で特に変わりが無いが、
finally という仕組みが追加されている。

try{
  // 失敗する可能性のある処理
}
catch{
  // 失敗したときの処理
}
finally {
  // 成功しようと失敗しようと最後に通る処理
}

17、桁あふれの監視

checked が有効なブロックでは桁あふれがあると例外が throw されます。
逆に throw させたく無い場合には unchecked をつけます。

checked{
  try{
    byte x = 255;
    x = (byte)(x + 1);
  }
  catch(System.OverflowException err){
    System.Console.WriteLine(err.Message);
  }
}

18、デリゲード

関数ポインタのようなもの。
デリゲートは加算していちどに複数の関数も呼べます。
減算して呼ぶ関数を消すこともできるようです。

delegate void Delegate(int a);

class Test{
  static void Main(){
    Delegate a = new Delegate(A);
    a += new Delegate(B);

    a(3);  // A(3) を呼び、次に B(3) を呼ぶことになる。
  }

  static void A(int n)
  {
    System.Console.WriteLine("A:" + n);
  }
  static void B(int n)
  {
    System.Console.WriteLine("B:" + n);
  }
}

19、イベント

デリゲートの発展系。
関数ポインタをメンバ関数から呼んでいる。

delegate void PrintCallback(int num);

class Print{
  private int num;
  public event PrintCallback PrintListener;
  public Print(int num){this.num = num;}
  public void StartEvent(){PrintListener(num);}
}

class Test{
  static void Main() {
    Print p = new Print(3);
    p.PrintListener += new PrintCallback(Action);
    //p.KittyListener();  // 不適切
    p.StartEvent();
  }
  static void Action(int num){
    System.Console.WriteLine(num);
  }	
}

実行結果

3

20、数学関数

System.Random や System.Math クラスが用意されている。

inserted by FC2 system