web-dev-qa-db-ja.com

.NET DefaultValue属性

私は人々がDefaultValue属性についていくつかの異なることを言っていると聞きました:

  • 「他の何かがそれを使用する前に、プロパティの値を設定します。」
  • 「自動プロパティでは機能しません。」
  • 「装飾用です。実際のデフォルト値を手動で設定する必要があります。」

どちらが正しいですか? DefaultValueは実際にデフォルト値を設定しますか?動作しない場合はありますか?それを使用しないのが最善ですか?

51
Aaron

私が通常DefaultValueを使用した場所は、XMLにシリアライズ/デシリアライズされたクラス用です。インスタンス化中にデフォルト値を設定しません。自動プロパティには影響しません。

MSDNから:

DefaultValueAttributeは、メンバーを属性の値で自動的に初期化しません。コードに初期値を設定する必要があります。

MSDN-DefaultValueAttributeクラス


編集:ローランドが指摘しているように、他の回答で言及されているように、属性はフォームデザイナでも使用されます

53
STW

これを4年後に更新するには:現在、JSON.netの DefaultValueHandling パラメーターを設定すると、Defaultaaが@aaronの期待どおりに機能します。

[JsonProperty("allowUploading",DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
[DefaultValue(true)]
public bool AllowUploading { get; set; }
16
John Hatton

すべての属性と同様に、メタデータであるため、「装飾専用です。実際のデフォルト値を手動で設定する必要があります。」最も近いです。

MSDNは、引き続き DefaultValueAttribute について述べています。

DefaultValueAttributeは、メンバーを属性の値で自動的に初期化しません。コードに初期値を設定する必要があります。

つまり、組み込みのXMLシリアル化などでコンストラクタを使用してプロパティをシリアル化するかどうかを判断できるように、コンストラクターを既定値であると一致させる必要があります。同様に、フォームデザイナはDefaultValuesを使用して、どのコードを自動生成する必要があるかを判断します。

12
Rowland Shaw

実際、どのクラスでも非常に簡単に動作するように「強制」できます。

最初に、System名前空間にオブジェクト拡張メソッドを記述する必要があります。

public static class ObjectExtensions
{
    public static void InitializePropertyDefaultValues(this object obj)
    {
        PropertyInfo[] props = obj.GetType().GetProperties();
        foreach (PropertyInfo prop in props)
        {
            var d = prop.GetCustomAttribute<DefaultValueAttribute>();
            if (d != null)
                prop.SetValue(obj, d.Value);
        }
    }
}

次に、実際にそのような自動デフォルト値の初期化を必要とするクラスの階層で十分に高いクラスのコンストラクターで、1行追加するだけです。

    public MotherOfMyClasses()
    {
        this.InitializePropertyDefaultValues();
    }
10
Thastograth

C#の最新バージョンでは、次のことができます。

public class InitParam
{
    public const int MyInt_Default = 32;
    public const bool MyBool_Default = true;

    [DefaultValue(MyInt_Default)]
    public int MyInt{ get; set; } = MyInt_Default;

    [DefaultValue(MyBool_Default)]
    public bool MyBool{ get; set; } = MyBool_Default;
}
4

「他の何かがそれを使用する前に、プロパティの値を設定します。」 ->いいえ、デフォルト値はデザイナー専用です。デフォルト値はデザイナーコードにシリアル化されません。

「自動プロパティでは機能しません。」 ->いいえ

「装飾用です。実際のデフォルト値を手動で設定する必要があります。」 ->いいえ。Designerのシリアル化のためです。ただし、手動で設定する必要があります。

2
gsharp

[〜#〜] msdn [〜#〜] ヘルプから:

AttributeCollection^ attributes = TypeDescriptor::GetProperties( this )[ "MyProperty" ]->Attributes;

/* Prints the default value by retrieving the DefaultValueAttribute 
      * from the AttributeCollection. */
DefaultValueAttribute^ myAttribute = dynamic_cast<DefaultValueAttribute^>(attributes[ DefaultValueAttribute::typeid ]);
Console::WriteLine( "The default value is: {0}", myAttribute->Value );

デフォルト値の属性を静的でないものに設定する必要があります。基本的にどのように設定したいのですか?


プロパティを保持するクラスのShouldSerialize関数をオーバーライドすることで解決しました。

例:

property System::String^ Z {
            System::String^ get(){...}
            void set(System::String^ value) {...}
        }

        bool ShouldSerializeZ() {
            return Z != <call to run time objects>
        }
1
Adam

afterthoughtやPostsharpなどのアスペクト指向フレームワークでこの種の魔法を実現できます。

0
Thomas Haller