Tips

C# 基礎 第17回 属性(プロパティ)

属性(プロパティ)

現実世界の人や物には、属性というのがあります。
例えば、人であれば名前、生年月日、住んでいる場所などです。
動物であれば、名前、種類、飼い主がいるか野生か、などですね。
山であれば、標高、所在地などでしょうか。
プログラミング世界の人や物(オブジェクト)にも属性があります。
今日は、オブジェクトの属性について学びましょう。

本日の内容
  1. 概要
  2. プロパティの宣言
  3. プロパティへの値設定
  4. プロパティからの値読み取り
  5. 問題
  6. まとめ

概要

プロパティはオブジェクトの属性であるデータのことです。
基本となる、自動実装プロパティと、
より細かい設定ができる手動実装プロパティがあります。

この記事では、基本となる自動実装プロパティに的を絞って説明をします。
手動実装プロパティについては、次回のメソッドが絡んでくるため、
次回、『セッター』とよばれる特殊なメソッドとともに、補足コラムとして取り上げます。

プロパティの種別
自動実装プロパティ
使用頻度が高い。書くのが簡単。
値の取得や設定では、単純に今ある値を返し、設定したい値を代入する。
手動実装プロパティ
値の取得や設定の時に複雑な処理をする。

(本日の内容一覧に戻る方はこちら)

プロパティの定義

プロパティは通常、部品クラスの中で定義します。
ここでは、プロパティの中でも、基本的な自動実装プロパティにしぼって、
定義に必要な設定項目を説明します。

プロパティを定義するために必要な要素
公開範囲
プロパティの値をどこまで公開するかです。
『全体に公開(public)』と『クラス内のみ公開(private)』をこの記事では紹介します。
データ型指定キーワード
プロパティのデータ型を表します。
プロパティ名
プロパティの名前です。
値の設定と取得の方法
プロパティの値を取得、設定するときの、制限を書く部分です。
既定値
コンストラクターで何も値を指定しなかった場合の値です。

公開範囲

プロパティの値をどこまで公開するかです。
全体に公開(public)の場合、クラスの外からでも自由に値を操作できます。
同じクラスの中だけに公開(private)している場合、クラスの中からのみ
値を取得したり、値を設定できます。
クラス外から値を取得、設定しようとするとコンパイルエラーです。

例えば、以下の例では、メインクラスから、外部のBirdクラスのHiddenNameに値を設定しようとしましたが、
HiddenNameはPrivateなので、エラーになっています。

publicとprivateの双方があるクラスの例
        using System;

        namespace TechPjin.CSharpTutorial.PropertyTutorial
        {
            class MainClass
            {
                static void Main(string[] args)
                {
                    var bird = new Bird();
                    bird.HiddenName = "hiddenBird";
                }
            }


            public class Bird
            {
                // 自クラス外も含めて全体に公開
                public  String Name { get; set;}

                // 自クラス内のみに公開
                private String HiddenName { get; set; }

                public  Bird()
                {
                }
            }
        }
        
privateのHiddenNameに値を設定しようとした結果

データ型指定キーワード

変数定義と同じです。
プロパティーのデータ型を指定しましょう。

プロパティのデータ型
  1. 文字列
  2. 整数
  3. 小数
  4. 真偽値
  5. コンテナ
  6. その他のクラスのもの(オブジェクト)
データ型の一例

プロパティ名

プロパティの名前です。
変数名の定義と基本的には同じです。
基本は名詞でつけましょう。
ただし、真偽値型の場合は、真偽がはっきりする文になるようにしましょう。
読んでそのまま何を表しているか意味のとおる名前にしましょう。
復習もかねて、変数名とプロパティ名に共通する名づけ原則をのせます。

変数名とプロパティー名に共通する名づけ原則
  1. 一文字の名前、略語は避けること
  2. なるべく英語を使うこと
  3. ローマ字の方式を統一すること

一方で、プロパティ名を名付けるときは、変数の名づけの時と異なる点もあります。
その中から2つご紹介します。

まず、プロパティを呼び出すときは、『変数名.プロパティ名』の形式になります。
この時、プロパティが真偽値型なら、『.』が日本語の『は/が』と同じ意味、
プロパティが真偽値型でないなら、『.』が日本語の『の』と同じ意味で読めるよう
名付けると、英語としての読みやすさが上がるので、名づけの際は気を付けてみてもいいでしょう。

もう一つ、変数の定義と違う点があります。
プロパティの名前は、頭文字も大文字(パスカルケース)にします
対照的に、変数名では、頭文字は小文字(キャメルケース)でしたね。

プロパティー名のつけ方(大文字小文字)
    public class Bird
            {
                // 最初が大文字の良い例
                public  String Name { get; set;}

                // 最初が小文字のダメな例
                public  int    name { get; set;}

                // 複合語は、句切れ目ごとに最初を大文字にする
                private String HiddenName { get; set; }

                public  Bird()
                {
                }
            }
    

値の設定と取得の方法

プロパティの値の再設定ができるかできないかに応じて、
3つの大きな区分けがあります。

区分け1. 自動計算プロパティ

事前に既定値か計算方法を指定します。
コンストラクターや代入による、外部からの値設定は一切不可です。

自動計算プロパティフォーマット
公開範囲 データ型 プロパティ名 = > 既定値;
namespace TechPjin.CSharpTutorial.PropertyTutorial
{   
    public class Animal
    {
        // 公開範囲は全体(public)、データ型は真偽値(bool)、属性名はIsAnimal、固定された初期値のみ
        public bool   IsAnimal     => true;
    }
}

区分け2. 再設定不可プロパティ

コンストラクターによる初期値設定のみ自由に可能です。
既定値の設定も可能です。
しかしながら、代入による値の再設定は不可です。

再設定不可プロパティの定義フォーマット
公開範囲 データ型 プロパティ名 {get;} (= 既定値;)
再設定不可プロパティの定義コード
namespace TechPjin.CSharpTutorial.PropertyTutorial
{   
    public class Animal
    { 
        // 公開範囲は全体(public)、データ型は文字列(string)、属性名はSpeciesName、再設定禁止{get;}
        public string SpeciesName  { get; }
    }
}

区分け3. 再設定自由プロパティ

初期値設定も再設定も自由。既定値の設定も可能。

再設定自由プロパティフォーマット
公開範囲 データ型 プロパティ名  {get; set;} (= 既定値;)
再設定自由プロパティの定義コード
namespace TechPjin.CSharpTutorial.PropertyTutorial
{   
    public class Animal
    {
        // 公開範囲は全体(public)、データ型は整数(int)、属性名はAge、再設定可能
        public int    Age          { get; set; }
    }
}

プロパティへの値再代入制限の実例

自動計算プロパティに値を、コンストラクターでセットしようとしても、コンパイルエラーになります。

初期値以外設定不可のプロパティに値をセットしようとした結果

自動計算プロパティと再設定不可プロパティに、
通常の方法で値を代入しようとしたときには、コンパイルエラーになります。

getだけのプロパティに値を設定しようとした結果

既定値

コンストラクターで何も値を指定しなかった場合の値です。
『=>』か『=』の後ろに指定します。

プロパティ定義実例

プロパティ定義のまとめを、フォーマット、ソースコードを紹介しながら行います。

プロパティ定義のフォーマット
クラス {
    公開範囲 データ型指定キーワード プロパティ名 再設定制限 ( = デフォルト値)
}
プロパティ定義のコード
namespace TechPjin.CSharpTutorial.PropertyTutorial
{
    public class Animal
    {

        // 公開範囲は全体(public)、データ型は真偽値(bool)、属性名はIsAnimal、固定された初期値のみ
        public bool   IsAnimal     => true;
 
        // 公開範囲は全体(public)、データ型は文字列(string)、属性名はSpeciesName、再設定禁止{get;}
        public string SpeciesName  { get; }

        // 公開範囲は全体(public)、データ型は文字列(string)、属性名はPersonalName、再設定禁止{get;}
        public string PersonalName { get; }

        // 公開範囲は全体(public)、データ型は整数(int)、属性名はAge、再設定可能
        public int    Age          { get; set; }

        // 公開範囲は全体(public)、データ型は真偽値(bool)、属性名はIsAlive、再設定可能、デフォルト値はtrue
        public bool   IsAlive      { get; set; } = true;

        // 公開範囲は全体(public)、データ型は真偽値(bool)、属性名はIsHungry、再設定可能。デフォルト値はfalse
        public bool   IsHungry     { get; set; } = false;

        // 引数付きコンストラクター
        public Animal(string speciesName, string personalName)
        {
            this.SpeciesName  = speciesName;
            this.PersonalName = personalName;
        }
    }
}

(本日の内容一覧に戻る方はこちら)

プロパティへの値設定

プロパティへの値設定で代表的な方法を2つ紹介します。
プロパティの値取得、設定の制限に応じて使い分けがあります。

プロパティへの値の設定方法
コンストラクターで最初に設定
コンストラクターに値を渡します
値設定制限指定がgetだけの時にはこれのみを使います
途中で代入
変数の代入と同じ形式で行います

コンストラクターで最初に設定

コンストラクターに値を渡します
値設定制限指定がgetだけの時にはこれのみを使います。
コンストラクターを定義する際に、プロパティ名の先頭を小文字にした引数名をつけます。

プロパティに値を設定するコンストラクター定義
// プロパティ名の最初を小文字にしたものを引数名にする
コンストラクター(引数1, 引数2)
{
    this.プロパティ1 = 引数1;
    this.プロパティ2 = 引数2;
    (以下略)

}
プロパティに値を設定するコンストラクターの呼び出し
new コンストラクター(引数1, 引数2, (以下略));
プロパティへの値設定例のソースコード
using System;
using static System.Console;

namespace TechPjin.CSharpTutorial.PropertyTutorial
{
    public class MainClass
    {
        public static void Main(string[] args)
        {
            /*
             コンストラクターによるプロパティへの値設定

             プロパティのSpeciesNameの最初を小文字にした引数speciesNameの値が、
             プロパティのSpeciesNameに入る。

             プロパティのPersonalNameの最初を小文字にした引数personalNameの値が、
             プロパティのPersonalNameに入る。
            */
            var rabbit = new Animal(speciesName: "Rabbit", personalName: "rab");
        }
    }

  public class Animal
    {
        // 公開範囲は全体(public)、データ型は文字列(string)、属性名はSpeciesName、再設定禁止{get;}
        public string SpeciesName  { get; }

        // 公開範囲は全体(public)、データ型は文字列(string)、属性名はPersonalName、再設定禁止{get;}
        public string PersonalName { get; }

        // 引数付きコンストラクター
        public Animal(string speciesName, string personalName)
        {
            this.SpeciesName  = speciesName;
            this.PersonalName = personalName;
        }
    }
}

通常の代入

変数の代入と同じ形式で行います

プロパティへの値設定法のフォーマット
変数名.プロパティ = 値;
プロパティへの値設定例のソースコード
using System;
using static System.Console;

namespace TechPjin.CSharpTutorial.PropertyTutorial
{
    class MainClass
    {
        static void Main(string[] args)
        {
            // 値の設定 コンストラクターを使って
            var rabbit = new Animal(speciesName: "Rabbit", personalName: "rab");

            // 値の設定 直接代入
            rabbit.Age = 3;
            rabbit.IsHungry = false;
        }
    }

}

(本日の内容一覧に戻る方はこちら)

プロパティからの値読み取り

『変数名.プロパティ名』という形式でつなげることで値を読み取ります。
まるで『.』でつながった一つの変数のように見えますね。

変数の値読み取りと同じ感覚で使っていただいて大丈夫です。

プロパティの使用法のフォーマット
変数名.プロパティ名
プロパティの使用例のソースコード
using System;
using static System.Console;

namespace TechPjin.CSharpTutorial.PropertyTutorial
{
    class MainClass
    {
        static void Main(string[] args)
        {
            // 値の設定 コンストラクターを使って
            var rabbit = new Animal(speciesName: "Rabbit", personalName: "rab");

            // 値の読み取り
            WriteLine(rabbit.PersonalName);
            WriteLine(rabbit.SpeciesName);
        }
    }

}
プロパティの使用結果の実行結果

(本日の内容一覧に戻る方はこちら)

問題

問題1. プロパティを定義してください

以下のConsoleFairyクラスに、名前(Name)と年齢(Age)のプロパティを定義してください。
Nameは全体に公開するプロパティとし、文字列型にし、再設定不可能にしてください。
Ageは全体に公開するプロパティとし、整数型にし、再設定可能にしてください。

課題コード
using System;
namespace TechPjin.CSharpTutorial.ConsoleFairyProject
{
    public class ConsoleFairy()
    {
        public ConsoleFairy()
        {
        }
    }
}
解答例
[csharp] using System;
namespace TechPjin.CSharpTutorial.ConsoleFairyProject
{
public class ConsoleFairy()
{
public string Name {get;}
public int Age {get; set;}

public ConsoleFairy()
{
}
}
}
[/csharp]

問題2. プロパティを設定するようコンストラクターを書き換えてください

以下のConsoleFairyクラスに、名前(Name)のプロパティを設定できるコンストラクターを作って下さい。

課題コード
using System;
namespace TechPjin.CSharpTutorial.ConsoleFairyProject
{
    public class ConsoleFairy()
    {
        public string Name {get;}
        public int    Age  {get; set;}

        public ConsoleFairy()
        {
        }
    }
}
解答例
[csharp] using System;
namespace TechPjin.CSharpTutorial.ConsoleFairyProject
{
public class ConsoleFairy()
{
public string Name {get;}
public int Age {get; set;}

public ConsoleFairy(string name)
{
this.Name = name;
}
}
}
[/csharp]

問題3. プロパティを設定してください

ConsoleFairyクラスのコンストラクターを呼び出してください。
コンストラクターで名前を設定し、
そのあとで、年齢を代入してください。

課題コード
using System;
namespace TechPjin.CSharpTutorial.ConsoleFairyProject
{
    class MainClass
    {
        static void Main(string[] args)
        {

        }
    }
}
解答例
[csharp] using System;
namespace TechPjin.CSharpTutorial.ConsoleFairyProject
{
class MainClass
{
static void Main(string[] args)
{
var consoleFairy = new ConsoleFairy(name: "Taro");
consoleFairy.Age = 10;
}
}
}
[/csharp]

問題4. プロパティの値を読み込んで、コマンドライン画面に書き込んでください

consoleFairyのNameとAgeをコマンドライン画面に表示してください。

課題コード
using System;
namespace TechPjin.CSharpTutorial.ConsoleFairyProject
{
    class MainClass
    {
        static void Main(string[] args)
        {
			var consoleFairy = new ConsoleFairy(name: "Taro");
			consoleFairy.Age = 10;
        }
    }
}
解答例
[csharp] using System;
namespace TechPjin.CSharpTutorial.ConsoleFairyProject
{
class MainClass
{
static void Main(string[] args)
{
var consoleFairy = new ConsoleFairy(name: "Taro");
consoleFairy.Age = 10;

Console.WriteLine($"{consoleFairy.Name}");
Console.WriteLine($"{consoleFairy.Age}");
}
}
}
[/csharp]

(本日の内容一覧に戻る方はこちら)

まとめ

属性を定義、設定、読み取りできるようになりましたね。
次回は、オブジェクトにいろいろと働いてもらうための方法『メソッド』を学んでいきましょう。

(本日の内容一覧に戻る方はこちら)

(最初から読み直したい方はこちら)

ゲーム制作関連のオススメ連載リンク

とっても手軽なゲーム制作体験!
Unityゲーム開発基礎

実際のリリースゲームを題材にしたハンズオンゲーム制作連載
実践unityゲーム開発

Recent News

Recent Tips

Tag Search