2014年4月4日

プロパティの比較

項目 C#.NET VB.NET
静的プロパティ
読込専用プロパティ
書込専用プロパティ
get, set 毎のアクセス修飾子
引数付きプロパティ
インデクサ
自動プロパティ
自動プロパティの
get, set 毎のアクセス修飾子
自動プロパティの初期化
自動プロパティの
バッキングフィールド
<PropertyName>k__BackingField _PropertyName
※VB.NET の get, set 毎のアクセス修飾子は、Visual Studio 2008/2010 で可能、2003 では不可であることを確認。
MSDN を信じると Visual Studio 2005 から可能。

  • C#.NET

using System;
using System.Reflection;

class CSharpProperties
{
    // 静的プロパティ
    public static int SValue
    {
        get { return -1; }
        set { Console.WriteLine(value); }
    }

    // 読取専用プロパティ
    public int RValue { get { return 0; } }

    // 書込専用プロパティ
    public int WValue { set { Console.WriteLine(value); } }

    // get, set 毎のアクセス修飾子
    public int RWValue
    {
        get { return 0; } // 省略時はプロパティと同じ = public
        private set { Console.WriteLine(value); }
    }

    // 引数付きプロパティ -> 不可
    // public string ParamValue[int index] { get { return index.ToString(); } set { } }

    // インデクサ
    public string this[int index]
    {
        get { return index.ToString(); }
        set { Console.WriteLine("[{0}] = {1}", index, value); }
    }

    // 自動プロパティ
    public int AutoValue { get; set; }

    // 自動プロパティの get, set 毎のアクセス修飾子
    public int RAutoValue { get; private set; } // 外部から読取専用
    public int WAutoValue { private get; set; } // 外部から書込専用

    // 自動プロパティの初期化 -> 不可
    // public int IAutoValue { get; set; } = 1;

    // 自動プロパティのバッキングフィールドへのアクセス -> リフレクションで可能
    public void AccessToAutoValue()
    {
        var fi = this.GetType().GetField("<AutoValue>k__BackingField",
                                         BindingFlags.Instance | BindingFlags.NonPublic);
        Console.WriteLine(fi.GetValue(this));
    }
}

  • VB.NET

Imports System

Class VbProperties
    ' 静的プロパティ
    Public Shared Property SValue As Integer
        Get
            Return -1
        End Get
        Set(value As Integer)
            Console.WriteLine(value)
        End Set
    End Property

    ' 読取専用プロパティ
    Public ReadOnly Property RValue As Integer
        Get
            Return 0
        End Get
    End Property

    ' 書込専用プロパティ
    Public WriteOnly Property WValue As Integer
        Set(value As Integer)
            Console.WriteLine(value)
        End Set
    End Property

    ' get, set 毎のアクセス修飾子
    Public Property RWValue As Integer
        Get
            Return 0
        End Get
        Private Set(value As Integer)
            Console.WriteLine(value)
        End Set
    End Property

   ' 引数付きプロパティ
    Public Property ParamValue(ByVal index As Integer) As String
        Get
            Return index.ToString()
        End Get
        Set(value As String)
            Console.WriteLine("[{0}] = {1}", index, value)
        End Set
    End Property

    ' インデクサ
    Default Public Property Item(ByVal index As Integer) As String
        Get
            Return index.ToString()
        End Get
        Set(value As String)
            Console.WriteLine("[{0}] = {1}", index, value)
        End Set
    End Property

    ' 自動プロパティ
    Public Property AutoValue As Integer

    ' 自動プロパティの get, set 毎のアクセス修飾子 -> 不可
    ' Public Property RAutoValue As Integer
    '     Get
    '     Private Set
    ' End Property

    ' 自動プロパティの初期化
    Public Property IAutoValue As Integer = 1

    ' 自動プロパティのバッキングフィールドへのアクセス -> 直に可能
    Public Sub AccessToAutoValue()
        Console.WriteLine(_AutoValue)
    End Sub
End Class

まとめ(感想のようなもの)

get, set 毎のアクセス修飾子を設定できる C# のプロパティは、とても便利。
しかもインデクサ、自動プロパティでも可能!!
C# は、自動プロパティで get, set 毎のアクセス修飾子を設定できる点が便利。
ただ、インデクサ以外の引数付きプロパティは使えない・・・残念。

対する VB の利点は、引数付きプロパティが使えること、自動プロパティが初期化できること。
欠点としては、バッキングフィールドに簡単にアクセスできること。
バッキングフィールドと同じ名前のメンバが定義できず、地味に不便。

おまけ

C# から VB の引数付きプロパティへのアクセスは下記で可能。
・・・ダサい。

var instance = new VbProperties();
// getter
var temp = instance.get_ParamValue(1);
// setter
instance.set_ParamValue(1, "a");

検証環境

Windows 7 64bit/Visual Studio 2010 SP1/.NET 4.0

参考URL

2 件のコメント:

  1. ん?VB.NET でもゲッター・セッターごとにアクセスレベル指定することは可能ですね。つか、いつも使ってます。確かVB2010 くらいから可能になってた筈です。

    http://msdn.microsoft.com/ja-jp/library/zzh9ha57.aspx

    返信削除
  2. ご指摘ありがとうございます。
    投稿を修正しました。

    返信削除