技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

.NET を理解する2

型について

.NET Framework の言語では、クラスとは独自に定義出来る型であり、値型、参照型、メソッド、属性、プロパティを含む事が出来ます。

// 属性
[Serializable]
public class SampleClass
{
    // 値型
    int id;
    
    // 参照型
    string name;
    
    // メソッド
    public void ShowStatus()
    {
        System.Console.WriteLine(id.ToString() + ":" + name);
    }
    
    // プロパティ(Java で言う getter/setter メソッド)
    public string Name
    {
        get { return this.name; }
        set { this.name = value; }
    }
    
    public int Id
    {
        get { return this.id; }
        set { this.id = value + 1; }
    }
}

また、クラスの継承(構造体は継承できません)、インターフェースの継承をサポートし、イベント機構を持ちます。
(イベントとは、特定条件下で、指定されたイベントハンドラをコールする仕組みです。)

クラスの継承では、親クラスの持つ全ての public メソッドを暗黙で引き継ぎ、protected なメンバーへのアクセスを可能にします。
C# では、意図しないオーバーライドを避けるため、virtual / override のペアが存在します。

class Parent
{
    public void Sample1() { ... }
    public virtual void Sample2() { ... }
}

class Child : Parent
{
    public void Sample1() { ... }
    public override void Sample2() { ... }
}

このとき、Child クラスの Sample1 ではコンパイル警告が出ます。
これは意図しないオーバーライドによって、親クラス(Parent)の Sample1 が無効になるという警告です。
Sample2 では、オーバーライドを前提としたメソッドに、オーバーライドを明示的にかけるため、正常に上書き出来ます。

意図して、親クラスのメソッドを隠蔽オーバーライド(10/28 bleis-tift様指摘)する場合、new キーワードを用いる事で、警告が外れます。

class Parent
{
    public void Sample1() { ... }
    public virtual void Sample2() { ... }
}

class Child : Parent
{
    public new void Sample1() { ... }
    public override void Sample2() { ... }
}

インターフェースでは、実装するべきメソッドを強制する事が出来ます。
また、インターフェースの一部メソッドのみ実装し、残りの実装を派生クラスで補う場合、abstract class を用いる事で実現出来ます。
abstract class は、直接インスタンスを作成する事の出来ないクラスです。

    public interface SampleInter
    {
        // interface のメンバーは常に public です。
        void Sample1();
        void Sample2();
    }

    public abstract class Parent : SampleInter
    {
        void SampleInter.Sample1()
        {
            throw new NotImplementedException();
        }

        public abstract void Sample2();
    }

    public class Child : Parent
    {
        public override void Sample2() { }
    }

また、継承してほしくないクラスに関しては、sealed 識別子を付ける事で、継承不可能にできます。
本質ではありませんが、partial 宣言を用いる事で、クラスの実装を複数ファイルにまたぐ事ができます。