【C#】プロパティとフィールド(メンバ変数)の決定的な違い!

この記事は約 6 分で読めます。

みなさんこんにちは!ひろぽんです!

今回はC#のプロパティとフィールド(メンバ変数)の違いについて書いていきたいと思います。

Privateなフィールド(メンバ変数)とPublicなプロパティならなんとなく違いが分かるかと思いますが、Publicなフィールド(メンバ変数)とPublicなプロパティってどう違うの?ってなる人も多いのではないでしょうか?

結論から言うと全く違います。

シマウマとウマくらい違います。

インドネシアとインドくらい違います。

中国と中国地方くらい違います。

っと本当に違うので、この記事で覚えていってください。

プロパティはフィールド(メンバ変数)へのアクセスする手段でしかない

結論はい!

ということです。

プロパティはフィールドにアクセスするためのものなのです。

一方のフィールドはメモリに値を一時的に保存するためのもの。いわば特定のClass内でのスコープが確保された変数といった感じです。

なので下記の書き方は

        private string _gender;
        public string Gender
        {
            get { return _gender; }
            set { _gender = value; }
        }

下記と一緒です。

        public string Gender { get; set; }

なんならこれとも一緒です。

        private string _gender;
        public string Gender
        {
            get => _gender;
            set => _gender = value;
        }

プロパティのおいしさ

じゃあプロパティとフィールドが違うのはわかったけど、プロパティは何がおいしいのか?という点になってくると思います。

結論から言うとプロパティは下記のことができます。

  • Datagridに値を表示できる
  • シリアライズしてXMLにできる
  • プロパティを動的に探して色々できる

Datagridに値を表示できる

例えば下記のようなクラスがあったとします。

    public class User
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public int Age;
        public string Address { get; set; }

        private string _gender;
        public string Gender
        {
            get => _gender;
            set => _gender = value;
        }

        public User(int age, int id, string name, string address,string gender)
        {
            Age = age;
            ID = id;
            Name = name;
            Address = address;
            _gender = gender;
        }

        public User()
        {
            
        }
    }

プロパティはIDとNameとAddressとGenderだけです。

Ageと_genderはあくまでもフィールドです。

で、上記のクラスのリストを作って、DatagridのDatasourceにします。

        private void Form1_Load(object sender, EventArgs e)
        {
            _users = new List<User>()
            {
                new User(20,1,"杉山","東京都","男")
                ,new User(30,2,"山田","愛知県","女")
                ,new User(25,3,"鈴木","秋田県","男")
            };
            dataGridView1.DataSource = _users;
        }

するとデータが表示できます。

Ageと_genderはフィールドなので表示はされていません。

シリアライズしてXMLにできる(Privateのみ出力できない)

次にシリアライズして外部にXMLを保存する場合です。

下記のようなXMLHelperを使って先ほど紹介したクラスを外部に保存してみます。

ジェネリックTのクラスをシリアライズして、保存したりデシリアライズして復元したりするクラスですね!

    public class XmlHelper<T> where T : class
    {
        public string TargetPath { get; set; }
        private Encoding encoding => System.Text.Encoding.GetEncoding("shift_jis");

        public XmlHelper(string targetPath)
        {
            TargetPath = targetPath;
        }

        public XmlHelper() : base()
        {
        }

        public void Save(T data)
        {
            var serializer = new XmlSerializer(typeof(T));
            using (var writer = new StreamWriter(TargetPath, false, encoding))
            {
                serializer.Serialize(writer, data);
                writer.Close();
            }
        }

        /// <summary>
        /// XMLファイルを読み込む
        /// </summary>
        public T Read()
        {
            var serializer = new XmlSerializer(typeof(T));
            T obj;
            using (var reader = new StreamReader(TargetPath, encoding))
            {
                obj = (T)serializer.Deserialize(reader);
                reader.Close();
            }
            return obj;
        }
    }

すると下記のような感じで保存できています。

ここではprivateなフィールドの_genderだけ出力できていません。

それ以外は出力できています。

プロパティを動的に探して色々できる

最後にプロパティは動的に検索ができます。

どういうことかというと、下記のコードを見てください。

            var props = typeof(User).GetProperties();

            var str = new StringBuilder();
            foreach (var user in _users)
            {
                foreach (var prop in props)
                {
                    str.Append($@"{prop.Name} : {prop.GetValue(user)}");
                    str.Append(Environment.NewLine);
                }
            }

            MessageBox.Show(str.ToString());

typeOf()で特定のクラスのType型を取得し、そのType型のGetPropaties関数をするとPropertyInfoの配列が返ってきます。

で、そのPropertyInfoにインスタンスを投げるとそのインスタンス内の指定のプロパティの値が取得できます。

上記の関数を実行すると下記のようになります。

ここではPublicフィールドでも出力されることはありません。

プロパティとフィールド(メンバ変数)は全く違った!

って事でプロパティとフィールドが全く違うことを証明できたかと思います!

以上!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA