たとえば System.Net.Sockets を使用するプログラムを記述した場合、「型または名前空間名 'Net' は名前空間 'System' に存在しません。アセンブリ参照が不足しています。」「型または名前空間名 'Socket' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。」などと表示されコンパイルできない。この場合、まず一番下位の識別子について、MSDN 等で調べてみる。
.NET Framework クラス ライブラリ
Socket クラスBerkeley ソケット インターフェイスを実装します。
名前空間 : System.Net.Sockets
アセンブリ : System (System.dll 内) http://msdn.microsoft.com/ja-jp/library/system.net.sockets.socket.aspx
「アセンブリ」の記述を確認したら、Visual C# の開発環境より [プロジェクト] → [参照の追加] を選択、[.NET] タブ内の「System」を選択して [OK] をクリックすると、ソリューションエクスプローラーの「参照設定」ノードの下位に「System」が現れる。再度コンパイルしてやはりエラーになるようなら、解決できない識別子についてさらにアセンブリ参照を追加する。
コンパイル時のエラーメッセージにはいくつかバリエーションがある。
System.IAsyncResult Delegate::BeginInvoke (orgparams, System.AsyncCallback callback, object @object); orgtype Delegate::EndInvake (System.IAsyncResult result);これらを呼び出すことによって、非同期の呼び出しを実現できる。
class MessageBox
{
// デリゲートを宣言
delegate System.Windows.Forms.DialogResult MessageBoxDelegate (string text, string caption, System.Windows.Forms.MessageBoxButtons buttons, System.Windows.Forms.MessageBoxIcon icon);
// メッセージボックスを表示するメソッド
System.Windows.Forms.DialogResult Show (string text, string caption, System.Windows.Forms.MessageBoxButtons buttons, System.Windows.Forms.MessageBoxIcon icon)
{
return System.Windows.Forms.MessageBox.Show (text, caption, buttons, icon);
}
static void Main ()
{
MessageBox msgBox = new MessageBox ();
// デリゲート作成
MessageBoxDelegate msgBoxDelegate = new MessageBoxDelegate (msgBox.Show);
// 非同期に呼び出す
System.IAsyncResult asyncResult = msgBoxDelegate.BeginInvoke ("ボタンが押されるのを待機します。", "待機中", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information, null, null);
// 終了まち
while (!asyncResult.IsCompleted)
{
System.Threading.Thread.Sleep (1000);
System.Console.WriteLine ("マダー?");
}
// 戻り値を取得
System.Windows.Forms.DialogResult result = msgBoxDelegate.EndInvoke (asyncResult);
}
}
// 動物クラス class Animal { protected string sName; public Animal () { sName = "unnamed"; } public string Name { get { return sName; } set { sName = value; } } } // 犬クラス class Dog : Animal { } // 猫クラス class Cat : Animal { static void Main () { object obj = new Cat (); Animal animal = obj as Animal; // obj は動物かな? if (animal == null) System.Console.WriteLine ("obj isn't animal."); else { System.Console.WriteLine (animal.Name); } Cat cat = obj as Cat; // obj は猫かな? if (cat == null) System.Console.WriteLine ("obj isn't cat."); else { cat.Name = "Kajino"; // 名前をつけよう! System.Console.WriteLine (cat.Name); if (animal != null) System.Console.WriteLine (animal.Name); // animal も同じ実体を参照している } Dog dog = obj as Dog; // obj は犬かな? if (dog == null) System.Console.WriteLine ("obj isn't dog."); else { System.Console.WriteLine (dog.Name); } } }上のコードの実行結果です。
unnamed Kajino Kajino obj isn't dog.obj は object 型の変数ですが、Cat クラスのオブジェクトへの参照を格納しています。Animal 型、Cat 型へのダウンキャストは成功しますが、Dog 型とは互換性がないため null が返されています。
object 型は、.NET Framework の Object のエイリアスです。C# の統一型システムでは、定義済みの型やユーザー定義の型、参照型や値型など、すべての型が、Object から直接的または間接的に継承されます。任意の型の値を object 型の変数に代入できます。値型の変数をオブジェクトに変換することを "ボックス化" と言います。型オブジェクトの変数を値型に変換することを "ボックス化解除" と言います。詳細については、「ボックス化とボックス化解除」を参照してください。 http://msdn.microsoft.com/ja-jp/library/9kkx3h3c(VS.80).aspxボックス化はボクシングとも呼ばれる。こちらのほうが好みだな。パンチ!パンチ!
class Test
{
static void Main ()
{
int num = 2000; // int は値型
object box = num; // ボクシング変換
num += 2500; // 元の値型を変更する
System.Console.WriteLine (num); // 元の値型は更新されている
System.Console.WriteLine (box); // こちらはヒープ上にコピーが作られているため更新されない
num = (int) box; // アンボクシング変換
System.Console.WriteLine (num); // ちゃんとキャストされたことがわかる
}
}
上記のコードを実行すると出力結果は下のようになる。
4500 2000 2000ボクシング変換を行うとヒープ上に object 型の実体が生成され、2000という値もヒープにコピーされる。元の変数を更新しても、ヒープ上の値は更新されない。
class Rainbow
{
private string[] sColors;
public Rainbow () { sColors = new string [] { "赤", "橙", "黄", "緑", "青", "藍", "紫" }; }
public string this [int index] // インデクサ宣言子
{
get { return sColors [index]; } // 取得用のアクセサ
set { sColors [index] = value; } // 設定用のアクセサ
}
public int Length
{
get { return sColors.Length; }
}
static void Main ()
{
Rainbow rainbow = new Rainbow ();
rainbow [1] = "orange"; // set が呼び出される
for (int i = 0; i < rainbow.Length; i ++)
System.Console.WriteLine (rainbow [i]); // get が呼び出される
}
}
こちらも set アクセサには暗黙の引数として value が渡される。代入された右辺値である。
class Cat
{
private string sName;
public string Name // プロパティ
{
get // 取得用のアクセサ
{
return sName;
}
set // 設定用のアクセサ
{
sName = value;
}
}
static void Main ()
{
Cat cat = new Cat ();
cat.Name = "タマ"; // set が呼び出される
System.Console.WriteLine (cat.Name); // get が呼び出される
}
}
set アクセサには、暗黙の引数として value が渡される。代入された右辺値である。
get または set のいずれかを省略することも可能。その場合、書き込み専用または読み取り専用となる。
abstract class Base
{
public void Hello () {}
}
class Inherit : Base
{
new public void Hello () {}
static void Main ()
{
Inherit iObj = new Inherit ();
// Base bObj = new Base (); この行はコンパイルできない
Base bObj = iObj;
iObj.Hello (); // Inherit のメソッドが実行される
bObj.Hello (); // Base のメソッドが実行される
}
}
メソッドを abstract 宣言した場合は内容を定義できない。派生側でオーバーライドする必要がある。
abstract class Base
{
public abstract void Hello (); // 実体はない
}
class Inherit : Base
{
public override void Hello () {}
static void Main ()
{
Inherit iObj = new Inherit ();
// Base bObj = new Base (); この行はコンパイルできない
Base bObj = iObj;
iObj.Hello (); // Inherit のメソッドが実行される
bObj.Hello (); // Inherit のメソッドが実行される
}
}
sealedclass Base {}
// class Inherit : Base {} コンパイルエラーとなる
同じように継承を禁止したメソッドも定義できる
class Base
{
public virtual void Hello () {}
}
class Inherit : Base
{
public sealed override void Hello () {}
}
class Inherit2 : Inherit
{
// public override void Hello () {} コンパイルエラーとなる
}
class Base
{
public virtual void Hello () {}
}
class Inherit : Base
{
public override void Hello () {}
static void Main ()
{
Inherit iObj = new Inherit ();
Base bObj = iObj;
iObj.Hello (); // Inherit のメソッドが実行される
bObj.Hello (); // Inherit のメソッドが実行される
}
}
class Base
{
public void Hello () {}
}
class Inherit : Base
{
new public void Hello () {} // new はなくても効果は一緒
static void Main ()
{
Inherit iObj = new Inherit ();
Base bObj = iObj;
iObj.Hello (); // Inheritのメソッドが実行される
bObj.Hello (); // Baseのメソッドが実行される
}
}
delegate void AnyMethod ();
class Test
{
static void Main ()
{
Test test = new Test ();
AnyMethod method = new AnyMethod (test.Hello);
method += new AnyMethod (test.Bye);
method ();
}
void Hello ()
{
System.Console.WriteLine ("Hello!");
}
void Bye ()
{
System.Console.WriteLine ("Bye!");
}
}
// Hello.cs
class Hello
{
static void Main ()
{
System.Console.WriteLine ("Hello World!");
}
}
TARGET = hello OBJS = hello.obj hello2.obj CC = cl.exe CFLAGS = /EHsc LD = link.exe LDFLAGS = /OUT:$(TARGET).exe .c.obj : $(CC) $(CFLAGS) /c $< .cpp.obj : $(CC) $(CFLAGS) /c $< all: $(OBJS) $(LD) $(OBJS) $(LDFLAGS) clean: del *.obj del *.exe