FrontPage  Index  Search  Changes  Login

C#

基本文法

ライブラリのインポート

using System;

パッケージ階層

 namespace Sample001 {
   public class Person {
   }
 }

複数の場合は更に囲うのか?

 namespace Outer {
   namespace Sample001 {
     public class Person {
     }
   }
 }

継承

 public class Taro : Person {}

継承できないようにする

sealed キーワードを使用する。下記はコンパイルエラーになる。

sealed class A  {}
class B : A {}

オーバーライド

  • キーワードを付けないとコンパイルエラーが出る。
  • java などの他言語のように必要な際にメソッドをオーバーライドすることができなくなるので、作成元に virtual を付けて欲しい旨のお伺いを立てないといけなくなる。
  • 暗黙の了解だと思っていたし、めんどいけど、意思統一するという点ではいいのかもしれない。
  • テストが書きにくいような

new を使用する。

必要性が分からない。継承元クラスの変数に突っ込むと呼ばれないので注意。

 public class Person {
   public string getName() {
     return "私には名前がありません。";
   }
 }
 public class Taro : Person {
   public new string getName() {
     return "私の名前は太郎";
   }
 }

実行結果

 new Taro().getName(); // => 私の名前は太郎
 Person p = new Taro();
 p.getName();          // => 私には名前がありません。

virtual と override を使用する

 public class Person {
   public virtual string getName() {
     return "私には名前がありません。";
   }
 }
 public class Taro : Person {
   public override string getName() {
     return "私の名前は太郎でオーバーライド";
   }
 }

実行結果

 new Taro().getName();  // => 私の名前は太郎
 Person p = new Taro();
 p.getName()            // => 私の名前は太郎

abstract クラス

クラスの宣言に abstract キーワードを使う。

 public abstract class Person {
   public abstract string getName();
 }
 public class Taro : Person {
   public override string getName() {
     return "my name is taro.";
   }
 }
 class Class1 {
   [STAThread]
     static void Main(string[] args) {
       Taro taro = new Taro();
       Console.WriteLine(taro.getName());
       Person someone = new Taro();
       Console.WriteLine(someone.getName());
     }
 }

interface

  • interface キーワードを使って宣言する。
  • java みたいに implements はなく継承と同じくコロンを使用する。
 public interface Person {
   string getName();
 }
 public class Taro : Person {
   public string getName() {
     return "my name is taro.";
   }
 }
 Person person = new Taro();
 person.getName();

データ型

予約語 別名 意味
sbyte System.SByte 符号付き8ビット整数
byte System.Byte 符号なし8ビット整数
short System.Int16 符号付き16ビット整数
ushort System.UInt16 符号なし16ビット整数
int System.Int32 符号付き32ビット整数
uint System.UInt32 符号なし32ビット整数
long System.Int64 符号付き64ビット整数
ulong System.UInt64 符号なし64ビット整数
char System.Char 文字型
float System.Single 単精度実数
double System.Double 倍精度実数
bool System.Boolean 論理型(falseとtrueのみ)
decimal System.Decimal 10進型
string System.String 文字列型

文字のバイト数を数える

 System.Text.Encoding encoding = System.Text.Encoding.GetEncoding("Shift_JIS");
 Console.WriteLine(encoding.GetByteCount("A"));        //=> 1
 Console.WriteLine(encoding.GetByteCount("あ"));       //=> 2
 // 該当する文字コードがないので ? が変える
 Console.WriteLine(encoding.GetByteCount("\x4e02"));   //=> 2
 encoding = System.Text.Encoding.GetEncoding("UTF-8");
 Console.WriteLine(encoding.GetByteCount("A"));        //=> 1
 Console.WriteLine(encoding.GetByteCount("あ"));       //=> 3
 Console.WriteLine(encoding.GetByteCount("\x4e02"));   //=> 3

ref と out

ref は変数の参照を渡す。メソッド引数内での改変を想定。
out は渡した変数に何かを入れてもらうことを明示する。メソッドで複数の結果を返せないことの回避用?

 private static void sample1(int x) {
   x++;
 }
 private static void sample2(ref int x) {
   x++;
 }
 private static void sample3(out int x) {
   x = 123;
 }
 [STAThread]
 static void Main(string[] args) {
   int a = 0;
   int b;
   sample1(a); //=> 0
   sample1(1);
   Console.WriteLine(a);

   int c = 0 , d;
   sample2(ref c);
   Console.WriteLine(c); //=> 1

   int e = 0 , f;
   sample3(out e);
   sample3(out f);
   Console.WriteLine(e); //=> 123
   Console.WriteLine(f); //=> 123
 }

小数計算

 float a = 0.3f;
 float b = 0.1f;
 float c = a - b;
 Console.WriteLine("{0}" , c); //=> 0.2

 decimal a2 = 0.3m;
 decimal b2 = 0.1m;
 Console.WriteLine("{0}" , a2 - b2); //=> 0.2

0.3 - 0.1 = 0.099999999 を期待したんだけど、きっちり(?)でる。丸め誤差は気にしなくていいのか? http://www.atmarkit.co.jp/fdotnet/csharp_abc2/csabc2_007/cs2_007_04.html

is 演算子

java の instanceof

 class Hi {
 }

 class Class1 {
     static void Main(string[] args) {
         Console.WriteLine("{0}" , (1 is int));
         Hi hi = new Hi();
         Console.WriteLine("{0}" , (hi is Hi));
     }
 }

キャスト

(Class2) を使ったキャストは、キャストできない場合は例外が発生する。通常のキャスト。

 Class2 instance3 = (Class2)instance1;

as はキャストできない場合に null を返す。

 Class2 instance2 = instance1 as Class2;
 //=> キャストできない場合は null

演算子のオーバーロード

+ や - といった演算子の挙動を変更することができる。

 using System;

 class Class2 {
   public string str;
   public Class2( string s) { str = s; }
   public static Class2 operator -(Class2 x) {
     return new Class2("-" + x.str);
   }
   public static Class2 operator +(Class2 x , Class2 y) {
     return new Class2( x.str + "+" + y.str);
   }
   public static Class2 operator -(Class2 x , Class2 y) {
     return new Class2(x.str + "-" + y.str);
   }
 }

 class Class1 {
   static void Main(string[] args) {
     Class2 a = new Class2("Hello");
     Class2 b = new Class2("World");
     Class2 c = a + b;
     Console.WriteLine(c.str);

     Class2 d = -c;
     Console.WriteLine(d.str);

     Console.WriteLine((a - b).str);
   }
 }

static イニシャライザ

java でいう static initializer
コンストラクタに static をつけたものが、最初のインスタンス生成前、または static メソッド呼び出し前に呼ばれる。

 class Class2 {
   static Class2() {
     Console.WriteLine("static Class2() called");
   }
   public Class2() {
     Console.WriteLine("constructor");
   }
   static public void special() {
     Console.WriteLine("static public special() called");
   }
 }

デストラクタ

 class Class2 {
   ~Class2() {
     Console.WriteLine("Class2's destructor called");
   }
 }

構造体

class を使う場合

 public class Test {
     public int v;
 }
 int count = 10000000;
 Test[] test = new Test[count];
 for (int i = 0 ; i < count ; i++) {
   test[i] = new Test();
   test[i].v = i;
 }

構造体を使う場合

 public struct Test {
     public int v;
 }
 int count = 10000000;
 Test[] test = new Test[count];
 for (int i = 0 ; i < count ; i++) {
   test[i].v = i;
 }

構造体を使うほうが早い。が、注意点もある。

クラスを用いる場合、1個のインスタンスは、1つの独立したメモリとして確保される。 つまり、メモリ確保という処理が1000万回実行されるのである。 これに対して、構造体の場合は、配列を作成した時点で1000万個分の構造体を収めるたった1個の巨大なメモリを確保している。 つまり、小さな処理を1000万回行うか、大きな処理を1回行うかの差が、この結果なのである。

構造体は値型なので、別の変数に代入する場合などには、丸ごと中身をコピーする羽目になり、処理効率を著しく落とす。 構造体はツボにはまれば効率アップできるが、一歩間違えると処理効率を大きく下げかねない危険がある

http://www.atmarkit.co.jp/fdotnet/csharp_abc2/csabc2_005/cs2_005_03.html

クラスの場合は参照渡しになるので変数格納時に遅くなることがない。

Generics

 List<String> list = new List<String> {
   "1","2"
 };
 list.ForEach(
   s => Console.WriteLine(s)
 );

匿名型

 var taro = new { Name = 'taro' , Age = 27 , Sex = "Male" };
 Console.WriteLine(taro.Name) //=> taro

ファイル

ファイル一覧

 using System;
 using System.IO;

 string[] files = Directory.GetFiles("src");
 foreach (string s in files) {
   Console.WriteLine(s);
 }

Win32 API

extern
処理の実体が外部にあることを示すキーワード
 using System;
 using System.Runtime.InteropServices;

 [DllImport("user32.dll")]
 public static extern int MessageBeep(uint uType);

 [STAThread]
 static void Main(string[] args) {
   MessageBeep(0);
 }
CallingConvention
呼び出し方法(stdcallなど)の種類を指定
CharSet
ANSIかUnicodeかを指定
EntryPoint
APIの真の名前を指定
ExactSpelling
名前の文字列が完全に一致する場合のみ利用可能とするかどうかを指定
PreserveSig
メソッドのシグネチャを保存することを指定
SetLastError
APIがエラーコードをSetLastError APIで設定するかどうかを指定
UnmanagedType.LPStr
Win32 APIのLPSTRを意味する
UnmanagedType.LPWStr
LPWSTRを意味する
 using System.Runtime.InteropServices;

 [DllImport("user32.dll" , CallingConvention=CallingConvention.Winapi,
     CharSet=CharSet.Ansi , EntryPoint="MessageBoxA" ,
     ExactSpelling=false , PreserveSig=true , SetLastError=false)]

 public static extern int MyMessageBox1(
   uint hWnd ,
   [MarshalAs(UnmanagedType.LPStr)] string lpText ,
   [MarshalAs(UnmanagedType.LPStr)] string lpCaption ,
   uint uType
 );

GUI

フォームの表示

 using System;
 using System.Drawing;
 using System.Windows.Forms;

 class Program {
   static void Main(string[] args) {
     Application.Run(new Form());
   }
 }

exe 実行時にコマンドプロンプトを表示しないためには、コンパイル時に /target:winexe を付ける。

csc /r:System.Drawing.dll /r:System.Windows.Forms.dll /target:winexe sample053.cs

ボタンの追加&イベント

 /*
  * http://ufcpp.net/study/csharp/lib_forms.html
  */
 using System;
 using System.Drawing;
 using System.Windows.Forms;

 class Program {
   static void Main(string[] args) {
     Application.Run(new Form1());
   }
 }

 class Form1 : Form {
   /** */
   private Button button1_ = null;
   /** */
   private int count_ = 0;
   /*
    *
    */
   public Form1() {
     this.Width  = 200;
     this.Height = 200;
     this.Text   = "サンプルプログラム";

     button1_ = new Button();
     button1_.Location = new Point(10,10);
     button1_.Size     = new Size(170,30);
     button1_.Text     = "ここを押して";
     button1_.Click += new EventHandler(button1_click);

     this.Controls.Add(button1_);
   }
   /*
    *
    */
   void button1_click(object sender , EventArgs e) {
     count_ ++;
     button1_.Text = count_.ToString();
   }
 }

コンパイル

ライブラリとしてコンパイル

 csc /t:library DynamicJson.cs
Last modified:2012/01/14 17:56:04
Keyword(s):
References:[FrontPage]