Je suis très nouveau en C #, alors s'il vous plaît, supportez-moi ...
J'implémente une classe partielle et j'aimerais ajouter deux propriétés comme suit:
public partial class SomeModel
{
public bool IsSomething { get; set; }
public List<string> SomeList { get; set; }
... Additional methods using the above data members ...
}
Je voudrais initialiser les deux membres de données: IsSomething
à True
et SomeList
à new List<string>()
. Normalement, je le ferais dans un constructeur, mais comme c'est une classe partielle, je ne veux pas toucher au constructeur (devrais-je?).
Quel est le meilleur moyen d'y parvenir?
Merci
PS Je travaille dans ASP.NET MVC, en ajoutant des fonctionnalités à un certain modèle, d'où la classe partielle.
Mis à jour pour C # 6
C # 6 a ajouté la possibilité d'attribuer une valeur par défaut aux propriétés automatiques. La valeur peut être n'importe quelle expression (il n'est pas nécessaire que ce soit une constante). Voici quelques exemples:
// Initialize to a string literal
public string SomeProperty {get;set;} = "This is the default value";
// Initialize with a simple expression
public DateTime ConstructedAt {get;} = DateTime.Now;
// Initialize with a conditional expression
public bool IsFoo { get; } = SomeClass.SomeProperty ? true : false;
Réponse originale
Les propriétés implémentées automatiquement peuvent être initialisées dans le constructeur de la classe, mais pas sur la propriété elle-même.
public SomeModel
{
IsSomething = false;
SomeList = new List<string>();
}
... ou vous pouvez utiliser une propriété basée sur le champ (un peu plus de travail) et initialiser le champ lui-même ...
private bool _IsSomething = false;
public bool IsSomething
{
get { return _IsSomething; }
set { _IsSomething = value; }
}
Mise à jour: Ma réponse ci-dessus ne clarifie pas le problème de cette classe partielle. La réponse de Mehrdad propose la solution consistant à utiliser une méthode partielle, ce qui est conforme à ma première suggestion. Ma deuxième suggestion d'utiliser des propriétés implémentées de manière non automatique (propriétés implémentées manuellement?) Fonctionnera dans cette situation.
La première propriété (IsSomething) est un booléen. Ce sera faux par défaut.
La deuxième propriété, puisqu'il s'agit d'un type de référence, sera par défaut à null sans aucun effort de votre part. Vous n'avez pas besoin de toucher le constructeur, car les types de référence (classes) commenceront automatiquement comme nuls dans .NET.
Si vous voulez utiliser une valeur autre que celle par défaut, vous avez deux options:
Tout d'abord, utilisez un champ de stockage de sauvegarde:
private bool isSomething = true;
public bool IsSomething {
get { return this.isSomething; }
set { this.isSomething = value; }
}
Deuxième option - ajoutez-le au constructeur.
Notez que la première option n'a pas de surcharge, c'est en gros ce que le compilateur fait lorsque vous utilisez une propriété automatique.
Vous ne pouvez pas avoir deux constructeurs dans deux parties d'une classe partielle. Cependant, vous pouvez utiliser méthodes partielles pour accomplir quelque chose comme ça:
// file1:
partial void Initialize();
public Constructor() {
// ... stuff ... initialize part 1
Initialize();
}
// file2:
void Initalize() {
// ... further initializations part 2 might want to do
}
Si aucune partie d'une classe partielle ne définit la méthode partielle, tous ses appels seront omis.
WARNING pour les utilisateurs de classes partielles WCF
Si vous essayez d'ajouter une propriété à une classe proxy WCF (générée par Ajouter une référence de service), vous serez peut-être surpris de constater que les champs privés ne sont pas initialisés car apparemment aucun constructeur n'est appelé .
Si vous essayez de faire cela (comme suggéré dans d'autres réponses), il ne sera jamais appelé:
private bool _sendEmail = true;
Cela n'a rien à voir avec le fait que le champ soit dans une classe partielle ou non.
Ce que vous devez faire est d’ajouter un attribut [OnDeserialized] qui vous permet d’initialiser davantage l’objet. Cela fait partie de System.Runtime.Serialization et n'est donc utile que dans le contexte de la sérialisation lorsque vous utilisez DataContractSerializer .
public partial class EndOfDayPackageInfo
{
[OnDeserialized()]
public void Init(StreamingContext context)
{
_sendEmail = true;
}
private bool _sendEmail;
public bool SendEmail
{
get
{
return _sendEmail;
}
set
{
_sendEmail = value;
RaisePropertyChanged("SendEmail");
}
}
}
Une autre approche consiste à «charger paresseux» la propriété - mais cette approche est beaucoup moins élégante.
private bool _sendEmail;
private bool _sendEmailInitialized;
public bool SendEmail
{
get
{
if (!_sendEmailInitialized)
{
_sendEmailInitialized = true;
_sendEmail = true; // default value
}
return _sendEmail;
}
set
{
if (!_sendEmailInitialized)
{
// prevent unwanted initialization if 'set' is called before 'get'
_sendEmailInitialized = true;
}
_sendEmail = value;
RaisePropertyChanged("SendEmail");
}
}
Pour cela, n'utilisez pas la propriété automatique, mais à l'ancienne
YourType _yourParameter = yourDefaultValue;
public YourType YourParameter
{
get{return _yourParameter;}
set{_yourParameter=value;}
}
Pour les utilisateurs de la version 6.0 de C #, il est possible d’initialiser les propriétés comme ceci:
public bool IsSomething { get; set; } = true;
public List<string> SomeList { get; set; } = new List<string>();
Vos deux propriétés auront déjà les valeurs par défaut requises.
Il n'y a rien de mal à avoir un constructeur dans une classe partielle. Les classes partielles ne sont nullement spéciales, hormis le fait que leur code source est réparti sur plusieurs fichiers/déclarations.
private bool _InternalUserContactUpdate = false;
public bool InternalUserContactUpdate
{
get { return _InternalUserContactUpdate; }
set { _InternalUserContactUpdate = value; }
}
Ensuite, lorsque vous souhaitez remplacer la valeur à condition,
if(!objUserModel.FirstName.ToLower().Equals(entry.Key[0].Attributes.Contains("firstname").ToString().ToLower()))
{
objUserModel.InternalUserContactUpdate= true;
}
J'espère que cela aidera