Comment donner à une propriété C# Auto une valeur par défaut?
comment attribuer une valeur par défaut à une propriété C# Auto? J'utilise soit le constructeur, soit l'ancienne syntaxe.
utilisant le constructeur:
class Person
{
public Person()
{
Name = "Default Name";
}
public string Name { get; set; }
}
utilisant la syntaxe de propriété normale (avec une valeur par défaut)
private string name = "Default Name";
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
y a-t-il un meilleur moyen?
21 réponses
En C# 5 et versions antérieures, pour donner automatique de la mise en œuvre des propriétés d'une valeur par défaut, vous devez le faire dans un constructeur.
la capacité d'avoir des initialisateurs de propriétés automatiques est incluse depuis C# 6.0. La syntaxe est:
public int X { get; set; } = x; // C# 6 or higher
Modifier 1/2/15
avec C# 6 Vous pouvez initialiser les auto-propriétés directement (enfin!), il y a maintenant d'autres réponses dans le fil qui les décrivent.
pour C# 5 et inférieur:
Si l'utilisation prévue de l'attribut n'est pas réellement définir les valeurs des propriétés, vous pouvez utiliser la réflexion pour définir toujours de toute façon...
public class DefaultValuesTest
{
public DefaultValuesTest()
{
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
{
DefaultValueAttribute myAttribute = (DefaultValueAttribute)property.Attributes[typeof(DefaultValueAttribute)];
if (myAttribute != null)
{
property.SetValue(this, myAttribute.Value);
}
}
}
public void DoTest()
{
var db = DefaultValueBool;
var ds = DefaultValueString;
var di = DefaultValueInt;
}
[System.ComponentModel.DefaultValue(true)]
public bool DefaultValueBool { get; set; }
[System.ComponentModel.DefaultValue("Good")]
public string DefaultValueString { get; set; }
[System.ComponentModel.DefaultValue(27)]
public int DefaultValueInt { get; set; }
}
quand vous insérez une valeur initiale pour une variable, cela sera fait implicitement dans le constructeur de toute façon.
je dirais que cette syntaxe est la meilleure pratique en C# jusqu'à 5:
class Person
{
public Person()
{
//do anything before variable assignment
//assign initial values
Name = "Default Name";
//do anything after variable assignment
}
public string Name { get; set; }
}
comme cela vous donne le contrôle clair des valeurs d'ordre sont attribuées.
à partir de C#6 Il y a une nouvelle voie:
public string Name { get; set; } = "Default Name"
DefaultValueAttribute ne fonctionne que dans le vs designer. Il n'initialisera pas la propriété à cette valeur.
Voir DefaultValue attribut ne fonctionne pas avec mon Auto Propriété
parfois j'utilise ceci, si Je ne veux pas qu'il soit réellement mis et persisté dans mon db:
class Person
{
private string _name;
public string Name
{
get
{
return string.IsNullOrEmpty(_name) ? "Default Name" : _name;
}
set { _name = value; }
}
}
évidemment si ce n'est pas une chaîne de caractères, alors je pourrais rendre l'objet nul ( double?, int? ) et vérifier si elle est null, le retour d'un défaut, ou le retour de la valeur de sa valeur.
alors je peux faire une vérification dans mon dépôt pour voir si c'est mon défaut et ne pas persister, ou faire une vérification de backdoor pour voir l'état vrai de la valeur de soutien, avant économie.
Espère que ça aide!
à partir de C# 6.0 , nous pouvons attribuer une valeur par défaut aux propriétés auto-implémentées.
public string Name { get; set; } = "Some Name";
nous pouvons aussi créer une propriété auto implémentée en lecture seule comme:
public string Name { get; } = "Some Name";
En C# 6.0 c'est un jeu d'enfant!
vous pouvez le faire dans la déclaration Class
elle-même, dans les déclarations de propriété.
public class Coordinate
{
public int X { get; set; } = 34; // get or set auto-property with initializer
public int Y { get; } = 89; // read-only auto-property with initializer
public int Z { get; } // read-only auto-property with no initializer
// so it has to be initialized from constructor
public Coordinate() // .ctor()
{
Z = 42;
}
}
dans la Version de C# (6.0) et plus , vous pouvez faire:
Pour les propriétés Readonly
public int ReadOnlyProp => 2;
pour les biens inscriptibles et déchiffrables
public string PropTest { get; set; } = "test";
dans la version actuelle de C# (7.0) , vous pouvez faire: (le snippet plutôt affiche comment vous pouvez utiliser l'expression corsé obtenir / définir des accesseurs pour faire est plus compact quand avec l'aide de champs de sauvegarde)
private string label = "Default Value";
// Expression-bodied get / set accessors.
public string Label
{
get => label;
set => this.label = value;
}
petit échantillon complet:
using System.ComponentModel;
private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
get { return bShowGroup; }
set { bShowGroup = value; }
}
ma solution est d'utiliser un attribut personnalisé qui fournit la valeur par défaut initialisation de la propriété par constante ou en utilisant le type de propriété initializer.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class InstanceAttribute : Attribute
{
public bool IsConstructorCall { get; private set; }
public object[] Values { get; private set; }
public InstanceAttribute() : this(true) { }
public InstanceAttribute(object value) : this(false, value) { }
public InstanceAttribute(bool isConstructorCall, params object[] values)
{
IsConstructorCall = isConstructorCall;
Values = values ?? new object[0];
}
}
Pour utiliser cet attribut, il est nécessaire d'hériter d'une classe de base classe de l'initialiseur ou l'utilisation d'une assistance statique méthode:
public abstract class DefaultValueInitializer
{
protected DefaultValueInitializer()
{
InitializeDefaultValues(this);
}
public static void InitializeDefaultValues(object obj)
{
var props = from prop in obj.GetType().GetProperties()
let attrs = prop.GetCustomAttributes(typeof(InstanceAttribute), false)
where attrs.Any()
select new { Property = prop, Attr = ((InstanceAttribute)attrs.First()) };
foreach (var pair in props)
{
object value = !pair.Attr.IsConstructorCall && pair.Attr.Values.Length > 0
? pair.Attr.Values[0]
: Activator.CreateInstance(pair.Property.PropertyType, pair.Attr.Values);
pair.Property.SetValue(obj, value, null);
}
}
}
exemple d'utilisation:
public class Simple : DefaultValueInitializer
{
[Instance("StringValue")]
public string StringValue { get; set; }
[Instance]
public List<string> Items { get; set; }
[Instance(true, 3,4)]
public Point Point { get; set; }
}
public static void Main(string[] args)
{
var obj = new Simple
{
Items = {"Item1"}
};
Console.WriteLine(obj.Items[0]);
Console.WriteLine(obj.Point);
Console.WriteLine(obj.StringValue);
}
sortie:
Item1
(X=3,Y=4)
StringValue
en plus de la réponse déjà acceptée, pour le scénario où vous voulez définir une propriété par défaut comme une fonction d'autres propriétés, Vous pouvez utiliser notation du corps d'expression sur C#6.0 (et plus) pour des constructions encore plus élégantes et concises comme:
public class Person{
public string FullName => $"{First} {Last}"; // expression body notation
public string First { get; set; } = "First";
public string Last { get; set; } = "Last";
}
vous pouvez utiliser ce qui précède de la façon suivante
var p = new Person();
p.FullName; // First Last
p.First = "Jon";
p.Last = "Snow";
p.FullName; // Jon Snow
pour pouvoir utiliser la notation ci-dessus"=>", la propriété doit être lue seulement, et vous n'utilisez pas le mot-clé get accessor.
détails sur MSDN
en C# 6 et au-dessus vous pouvez simplement utiliser la syntaxe:
public object Foo { get; set; } = bar;
notez que pour avoir une propriété readonly
omettez simplement l'ensemble, comme suit:
public object Foo { get; } = bar;
vous pouvez également assigner readonly
auto-propriétés du constructeur.
auparavant, j'ai répondu comme suit.
j'éviterais d'ajouter un défaut au constructeur; laisser cela pour les assignations dynamiques et éviter d'avoir deux points où la variable est assignée (i.e. le type default et dans le constructeur). En général, j'écrirais simplement une propriété normale dans de tels cas.
une autre option est de faire ce que ASP.Net does and define defaults via un attribut:
http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx
dans le constructeur. Le but du constructeur est d'initialiser ses membres de données.
avez-vous essayé d'utiliser les méthodes DefaultValueAttribute ou ShouldSerialize et Reset en conjonction avec le constructeur? Je pense que l'une de ces deux méthodes est nécessaire si vous faites une classe qui pourrait apparaître sur la surface du concepteur ou dans une grille de propriété.
public Class ClassName{
public int PropName{get;set;}
public ClassName{
PropName=0; //Default Value
}
}
Personnellement, je ne vois pas l'intérêt d'en faire une propriété, si vous n'allez pas faire quoi que ce soit au-delà de l'auto-propriété. Il suffit de laisser un champ. L'avantage d'encapsulation pour ces articles sont juste des harengs rouges, parce qu'il n'y a rien derrière eux pour encapsuler. Si vous avez besoin de changer l'implémentation sous-jacente, vous êtes toujours libre de les reformater en propriétés sans casser aucun code dépendant.
Hmm... peut-être que ce sera le sujet de sa propre question plus tard
pour clarifier, oui, vous devez définir des valeurs par défaut dans le constructeur pour les objets dérivés de la classe. Vous devrez assurer le constructeur existe avec le bon modificateur d'accès pour la construction. Si l'objet n'est pas instancié, par exemple s'il n'a pas de constructeur (par exemple méthodes statiques), alors la valeur par défaut peut être définie par le champ. Le raisonnement ici est que l'objet lui-même sera créé qu'une seule fois et vous n'avez pas l'instancier.
@Darren Kopp - bonne réponse, propre et correcte. Et pour le répéter, vous pouvez écrire des constructeurs pour des méthodes abstraites. Vous avez juste besoin d'y accéder depuis la classe de base lorsque vous écrivez le constructeur:
constructeur à la classe de Base:
public BaseClassAbstract()
{
this.PropertyName = "Default Name";
}
Constructeur à la Dérivée de / en Béton / Sous-Catégorie:
public SubClass() : base() { }
le point ici est que la variable d'instance tirée de la classe de base peut enterrer votre nom de champ de base. Réglage de l'actuel objet instancié de la valeur à l'aide de "ce."vous permettra de former correctement votre objet par rapport à l'instance courante et aux niveaux de permission requis (modificateurs d'accès) où vous l'instanciez.
utiliser le constructeur parce que"lorsque le constructeur est terminé, la Construction doit être terminée". les propriétés sont comme les états que vos classes contiennent, si vous deviez initialiser un état par défaut, vous le feriez dans votre constructeur.
class Person
{
/// Gets/sets a value indicating whether auto
/// save of review layer is enabled or not
[System.ComponentModel.DefaultValue(true)]
public bool AutoSaveReviewLayer { get; set; }
}
je pense que ça ferait l'affaire si tu donnais à Quelqu'un un retard de false.
private bool _SomeFlagSet = false;
public bool SomeFlag
{
get
{
if (!_SomeFlagSet)
SomeFlag = false;
return SomeFlag;
}
set
{
if (!_SomeFlagSet)
_SomeFlagSet = true;
SomeFlag = value;
}
}
initialise en ligne, utiliser les constructeurs pour initialiser est une mauvaise pratique et entraînera plus de changements de rupture plus tard.