C# カプセル化・プロパティ


インスタンスを実装する

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace count
{
    internal class Program
    {
        static void Main(string[] args)
        {
            CountNumber c = new CountNumber(2);
            //var c = new CountNumber;
            Console.WriteLine(c.GetCount());
            c.Call();
            Console.WriteLine(c.GetCount());


            Console.ReadLine();

        }

        class CountNumber
        {
            private int _count = 0;

            public CountNumber(int count)
            {
                _count = count;
            }

            public void Call()
            {
                _count++;
            }

            public int GetCount()
            {
                return _count;

            }
        }
    }
}

カプセル化

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace count
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var input = int.Parse(Console.ReadLine());
            var counter = new Counter(input);
            counter.GetCounter();

            Console.ReadLine();


        }

        public class Counter
        {
            private int _count = 0;

            public Counter(int count)
            {
                SetCount(count);
            }
            
            public void Call()
            {
                _count++;
            }

            public void SetCount(int value)
            {
                if(value < 0)
                {
                    return;
                }
                else
                {
                    _count = value;
                }
            }

            public void GetCounter()
            {
                Console.WriteLine(_count);
            }
        }

    }
}


プロパティ

  • 特殊なメソッドのこと。

  • Javaなどにはない!

    • 普通の値のように使えるけど、カプセル化に使用可能!

    • 値の読み取り・書き込み専用!シンプル!

    • 自動実装プロパティにできる!

using System;

namespace CountPro
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Enter a number: ");  // ユーザーに入力を促す
            var input = int.Parse(Console.ReadLine());
            var counter = new Counter(input);
            counter.Call();
            counter.GetCounter();

            Console.ReadLine();
        }

        public class Counter
        {
            private int _count;  // バッキングフィールド

            public Counter(int count)
            {
                Count = count;  // プロパティを通じて初期値を設定
            }

            // プロパティCountを定義
            public int Count
            {
                get => _count;  // _countの値を返す
                set => _count = value < 0 ? 0 : value;  // valueが0未満の場合は0を、そうでなければvalueを_countに設定
            }

            public void Call()
            {
                Count++;  // Countプロパティを通じて_countをインクリメント
            }

            public void GetCounter()
            {
                Console.WriteLine(Count);  // Countプロパティの現在値を表示
            }
        }
    }
}

以下のような書きかたもアリ(展開しただけ)

get 
{ 
    return _count; // _countの値を返す 
}   
set 
{ 
    _count = value < 0 ? 0 : value; // valueが0未満の場合は0を、そうでなければvalueを_countに設定 
}  

プロパティはC#で使われる、フィールド(クラス内の変数)へのアクセスを制御するための特別な方法です。プロパティを使用することで、フィールドへの読み書き操作をより詳細に制御できます。プロパティにはgetアクセサーとsetアクセサーの二つがあり、それぞれフィールドの値を読み出し、設定するために使われます。

get アクセサー

getアクセサーは、プロパティの値を読み出すために使われます。このアクセサーが呼ばれると、プロパティは内部的に保持しているフィールドの値を返します。アクセスするたびに計算や変換を行うこともできます。

set アクセサー

setアクセサーは、プロパティの値を新しい値で設定するために使われます。このアクセサーが呼ばれると、指定された新しい値(valueキーワードを通じてアクセス可能)を内部的に保持しているフィールドに代入します。このとき、入力値の検証や変換を行うこともできます。

サンプルコードでの使用例

先ほどの修正されたCounterクラスにおけるCountプロパティを例にとって説明します。

csharpCopy code

public int Count { get => _count; // _countの値を返す set => _count = value < 0 ? 0 : value; // valueが0未満の場合は0を、そうでなければvalueを_countに設定 }

  • getアクセサー: このコードでは、getアクセサーは単純にプライベートフィールド_countの現在値を返します。つまり、Countプロパティを読み出すと、_countの値が得られます。

  • setアクセサー: setアクセサーでは、設定しようとする新しい値(value)が0未満かどうかをチェックしています。もし0未満であれば、_countを0に設定し、そうでなければvalueをそのまま_countに代入します。これにより、Counterクラスのインスタンスが負のカウント値を持たないように保証されています。

メソッドとの関連

プロパティは、実質的にはメソッド(getメソッドとsetメソッド)として動作しますが、フィールドに似た文法でアクセスできるように設計されています。これにより、外部からのアクセス時に内部状態の保護と、任意のロジックの実行を組み合わせることができます。プロパティの使用により、クラスの実装詳細を隠蔽しつつ、使用する側にはシンプルなインターフェースを提供できます。

例えば、CallメソッドではCountプロパティを通じて_countフィールドをインクリメントしていますが、これはsetアクセサーのロジック(この場合は値が0未満にならないようにする)を自動的に利用することを意味します。同様に、GetCounterメソッドでCountプロパティの値を取得するときは、getアクセサーを通じて安全に値を読み出しています。

問題 1: 知識問題

プロパティにおけるgetsetアクセサーの役割について説明してください。また、プロパティを利用するメリットについて二つ挙げてください。


問題 2: コーディング問題

以下の仕様を満たすC#のクラスを作成してください。

  • クラス名: Product

  • プロパティ:

    • Name (文字列): 製品名。外部から読み取り可能だが、クラス外部からは設定不可。

    • Price (整数): 製品の価格。0以上の値のみ設定可能。外部から読み書き可能。

  • コンストラクタ:

    • Product(string name, int price):製品名と価格を受け取り、それぞれのプロパティに設定する。ただし、価格が0未満の場合は0を設定する。

  • メソッド:

    • PrintProductInfo(): コンソールに製品の名前と価格を表示する。


答え 1:

getアクセサーはプロパティの値を読み取るために使用されます。クラス外部からプロパティにアクセスした際に、getアクセサーが呼ばれ、プロパティの現在値が返されます。

setアクセサーはプロパティの値を設定するために使用されます。新しい値をプロパティに代入しようとした際にsetアクセサーが呼ばれ、特別なキーワードvalueを通じて新しい値を受け取ります。

プロパティを利用するメリット:

  1. カプセル化: プロパティを通じてクラスのフィールドへのアクセスを制御することで、クラスの内部状態を保護し、外部からの直接的なアクセスを防ぐことができます。

  2. 柔軟性: getsetアクセサー内にロジックを追加することで、フィールドの値を読み書きする際の振る舞いをカスタマイズできます。これにより、値の検証や変更通知などの機能を実装することができます。

回答2:サンプルコード

using System;

public class Product
{
    public string Name { get; private set; }  // 外部からの設定不可
    private int _price;

    public int Price
    {
        get => _price;
        set => _price = value < 0 ? 0 : value;  // 価格が0未満の場合は0を設定
    }

    public Product(string name, int price)
    {
        Name = name;
        Price = price;  // プロパティを通じて価格を設定し、ロジックを適用
    }

    public void PrintProductInfo()
    {
        Console.WriteLine($"Product: {Name}, Price: {Price}");
    }
}

// 使用例
class Program
{
    static void Main()
    {
        var product = new Product("Example Product", -100);
        product.PrintProductInfo();  // Product: Example Product, Price: 0
    }
}

この記事が気に入ったらサポートをしてみませんか?