Je pense que cette question est un cas particulier d'une question plus générale sur la création de sécurité de type à travers une application C#. Mon exemple ici est avec 2 types de données: les prix et les poids. Ils ont différentes unités de mesure, donc on ne devrait jamais essayer d'attribuer un prix à un poids ou vice versa. Les deux sous les couvertures sont vraiment des valeurs décimales. (J'ignore le fait qu'il pourrait y avoir des conversions comme des livres en kilogrammes etc.) Cette même idée pourrait être appliquée aux chaînes avec des types spécifiques comme EmailAddress et UserLastName. Avec un peu de code de plaque de chaudière, on peut effectuer une conversion explicite ou des conversions implicites entre les types spécifiques: Prix et Poids, et le type sous-jacent Décimal. Avec les remplacements d'opérateurs "explicites", on obtient un ensemble plus restrictif de choses que l'on peut faire avec ces classes. Vous devez être manuellement cas chaque fois que vous passez d'un type à l'autre. Par exemple:
public void NeedsPrice(Price aPrice)
{
}
public void NeedsWeight(Weight aWeight)
{
}
public void NeedsDecimal(Decimal aDecimal)
{
}
public void ExplicitTest()
{
Price aPrice = (Price)1.23m;
Decimal aDecimal = 3.4m;
Weight aWeight = (Weight)132.0m;
// ok
aPrice = (Price)aDecimal;
aDecimal = (Decimal)aPrice;
// Errors need explicit case
aPrice = aDecimal;
aDecimal = aPrice;
//ok
aWeight = (Weight)aDecimal;
aDecimal = (Decimal) aWeight;
// Errors need explicit cast
aWeight = aDecimal;
aDecimal = aWeight;
// Errors (no such conversion exists)
aPrice = (Price)aWeight;
aWeight = (Weight)aPrice;
// Ok, but why would you ever do this.
aPrice = (Price)(Decimal)aWeight;
aWeight = (Weight)(Decimal)aPrice;
NeedsPrice(aPrice); //ok
NeedsDecimal(aPrice); //error
NeedsWeight(aPrice); //error
NeedsPrice(aDecimal); //error
NeedsDecimal(aDecimal); //ok
NeedsWeight(aDecimal); //error
NeedsPrice(aWeight); //error
NeedsDecimal(aWeight); //error
NeedsWeight(aWeight); //ok
}
changeant seulement les opérateurs « explicites » les opérateurs à « implicites » en remplaçant les mots « explicite » par « implicite » dans le code, on peut convertir dans les deux sens à la classe décimale sous-jacente sans travail supplémentaire. Cela fait que le prix et le poids se comportent plus comme une décimale, mais vous ne pouvez toujours pas modifier un prix par rapport à un poids. C'est généralement le niveau de sécurité que je recherche. Lorsque vous effectuez cette opération pour Chaîne au lieu de Décimal,
public void ImplicitTest()
{
Price aPrice = 1.23m;
Decimal aDecimal = 3.4m;
Weight aWeight = 132.0m;
// ok implicit cast
aPrice = aDecimal;
aDecimal = aPrice;
// ok implicit cast
aWeight = aDecimal;
aDecimal = aWeight;
// Errors
aPrice = aWeight;
aWeight = aPrice;
NeedsPrice(aPrice); //ok
NeedsDecimal(aPrice); //ok
NeedsWeight(aPrice); //error
NeedsPrice(aDecimal); //ok
NeedsDecimal(aDecimal); //ok
NeedsWeight(aDecimal); //ok
NeedsPrice(aWeight); //error
NeedsDecimal(aWeight); //ok
NeedsWeight(aWeight); //ok
}
J'aime l'idée de la réponse de Thorarin à propos de la vérification de null et du retour de null dans la conversion. par exemple.
public static implicit operator EMailAddress(string address)
{
// Make
// EmailAddress myvar=null
// and
// string aNullString = null;
// EmailAddress myvar = aNullString;
// give the same result.
if (address == null)
return null;
return new EMailAddress(address);
}
Pour obtenir ces classes de travail en tant que clés de collections dictionnaire, vous aurez également besoin d'implémenter equals, GetHashCode, == opérateur, et l'opérateur! =
Pour rendre tout cela plus facile, je fis classe ValueType que je peux étendre, La classe ValueType appelle le type de base pour tout sauf les opérateurs de conversion.
Si cela ressemble à une chaîne - ce devrait être une chaîne. Je ne suis pas sûr que ce soit possible et même c'est une bonne idée. – zerkms
La classe de chaînes est-elle défectueuse? –
Personne ne s'attendrait à voir ce genre de chose. Créez simplement votre propre classe. –