C# imiter overridding de l'opérateur d'affectation (=)
J'ai eu un petit problème avec un quelque chose de simple classe wrapper j'ai.
Il ressemble à quelque chose comme ceci:
public class Wrapper<T>
{
private T _value;
public Wrapper<T>(T value)
{
_value = value;
}
public static implicit operator Wrapper<T>(T value)
{
return new Wrapper<T>(value);
}
public static implicit operator T(Wrapper<T> value)
{
return value._value;
}
}
J'ai remplacé l'implicite convertisseurs de et de T, de sorte qu'il se comporte presque comme une instance de T lui-même.
par exemple
Wrapper<int> foo = 42;
Cependant j'ai un léger problème lors de l'affectation d'une instance de Wrapper à un autre, car je ne veux affecter la valeur de la deuxième classe Wrapper.
Donc, pour l'instant, je dois faire ceci:
Wrapper<int> foo = 42;
Wrapper<int> bar = (int)foo;
Ou exposer _value du public par le biais d'une propriété.
Cependant, comme c'est dans une bibliothèque, et je ne veux pas que l'utilisateur dépendent de me souvenant de cela, avez-vous une idée de comment je pourrait imiter overridding de l'opérateur d'affectation ?
Le problème en changeant juste le pointeur (comme il le fait lors de l'affectation d'une instance de classe à l'autre), c'est que j'ai un dictionnaire de pointeurs vers ces objets wrappers, donc je ne peux pas les avoir en changeant tout le temps, depuis le dictionnaire serait cesser d'appariement ensuite.
Je peux voir si c'est un peu déroutant, donc si j'ai oublié quelque chose d'important, n'hésitez pas à demander 🙂
OriginalL'auteur | 2009-03-13
Vous devez vous connecter pour publier un commentaire.
Puisque l'opérateur d'affectation ne peut pas être surchargé, il n'y a pas une vraie bonne solution. Comme quelqu'un l'a souligné, à l'aide d'un struct vous donnera l'affectation de la sémantique que vous voulez, mais vous êtes confronté à la valeur sémantique--souvent pas une bonne chose.
Une option est de surcharger le constructeur:
Qui aurait pour résultat de cette syntaxe:
Bien plus détaillé que ce que vous avez, il lit mieux.
Ou vous pouvez ajouter un
Clone
méthode (pas leICloneable
interface), de sorte que l'on peut écrire:Vous pourriez obtenir vraiment créatif et la surcharge de certains opérateur de, de faire il n'essentiellement rien. Je ne recommande pas que, si. À l'aide de la surcharge d'opérateur pour ces sortes de choses typiquement rend le code plus compliqués et souvent des pauses.
OriginalL'auteur Jim Mischel
Vous pourriez faire Wrapper<T> un
struct
. Cependant, je ne suis pas si sûr que ce serait fonction de la conception de votre application ou pas.OriginalL'auteur zildjohn01
Si vous regardez Nullable<T>...qui fait une chose très semblable à ce que vous faites ici, il expose la valeur interne à l'aide d'un .La valeur de la propriété.
Je ne suis pas sûr que j'ai suivi ce, exactement ce que vous stockez dans le dictionnaire? Parce que si vous stockez des références, le CLR mise à jour en tant que de besoin.
OriginalL'auteur FlySwat
Ne pas implicitement exprimées votre enveloppe de deux manières.
Casting de
DBValue<T>
àT
est une perte de conversion (au minimum, vous perdez le fait que c'est une valeur de la base de données), et par les meilleures pratiques devraient être explicites. Si vous n'avez pas de perdre quoi que ce soit par la conversion deDBValue<T>
àT
, vous pourriez tout aussi bien utiliser les propriétés de retourT
.Fondamentalement, vous avez déjà vu pourquoi vous ne devriez pas essayer de le faire: si un DBValue peut être remplacé par T et dans l'autre sens, comment le compilateur (ou développeur) savoir lequel choisir?
Nécessitant l'aval, les développeurs d'écrire:
ou
au lieu de
...ce n'est pas contraignante, et permet de s'assurer que tout le monde sait exactement ce qu'il se passe.
EDIT:
Pour réellement répondre à la question, vous ne pouvez pas remplacer la référence à l'affectation ou à la faire ressembler que vous avez, mais vous ne devriez pas vraiment besoin.
OriginalL'auteur ajlane
C'est ce que les propriétés sont pour. Ils vous permettent de définir ce que l'affectation des moyens. Vous ne pouvez pas définir une classe ou structure elle-même, car ils sont déjà définis par la langue pour faire les choses nécessaires. Il suffit d'ajouter une
Value
propriété à la classe.Sinon, de modifier une question à donner une vision plus large de votre design et le comment de ce Wrapper s'inscrit, en tant que quelqu'un pourrait être en mesure de proposer une approche plus simple.
OriginalL'auteur Daniel Earwicker
Je viens de regarder, faire de la classe un struct est vraiment pas une option, car elle a une certaine logique dans le constructeur sans paramètre, en plus il hérite d'une classe abstraite, qui contient interne abstraite fonctions.
Je ne peux pas utiliser une interface, que ferait les fonctions publiques, ce qui permettrait de sortir de la logique entièrement.
Je peux poster l'ensemble de la classe si ce serait utile, mais il est un peu long (130 lignes)
Ou je pourrais jeter sur un autre serveur, si ce serait mieux ? (même si ça fait mal à l'intégrité de cette question, comme je peut le supprimer éventuellement à partir de ce serveur)
Aussi en train d'expliquer à la classe qui est vraiment difficile, sans l'écriture d'un essai complet :-/
De toute façon, je vais essayer d'illustrer le problème que je vais avoir.
Assumer 2 tableau des classes: CustomerTable et UserTable:
Maintenant, le problème est que certains autres développeurs peuvent utiliser le code ci-dessus comme suit:
Ce que le développeur doit, pour fonctionner, a été:
Le problème est cependant, qui dans leur bon esprit de penser que, lors de l'écriture de code ?
Même si j'ai utilisé une Valeur de propriété, le développeur devra toujours se souvenir pour écrire
Et, de nouveau, le développeur peut oublier cela, et tout d'un coup, il obtient des exceptions, ou pire: les données qui ne sont pas conservés dans la base de données.
Donc ma question est, que je veux le wrapper pour être totalement transparent (il devrait être utilisable comme si elle était en fait de la classe, du primitif, c'est l'emballage).
Cependant lors de l'attribution d'un wrapper pour l'autre, ma logique interne des pauses.
Ouf beaucoup de l'écriture, et beaucoup de code - permettez-moi de savoir si j'ai trop écrit.
OriginalL'auteur
Un J Lane je vois ce que tu veux dire, et je suppose que vous avez raison, je voulais juste le rendre aussi simple que possible à utiliser la bibliothèque.
La raison pour laquelle le cast implicite de DbValue à T, est tout simplement de fonctions qui attend T.
par exemple
plutôt que
Cela nécessite le cast implicite.
Cela étant dit, je viens de lire votre commentaire tout en tapant ceci, et je peux le voir, c'est tout à fait la question.
Je pense que je vais retourner à l'exposant de la valeur grâce à une propriété, il faut juste le développeur de type plus, et fait un peu le code laid, je pense.
Imaginez DbValue:
Mais là encore, il est probablement mieux avec "laid" de code, de code qui se comporte différemment de ce que vous attendez simplement en le lisant.
Je pense que cette question se termine comme une "meilleure pratique" question vraiment.
Alors, pour conclure, je vais créer une Valeur de la propriété et de l'utiliser à la place de conversions implicites, et le développeur à l'aide de la bibliothèque juste à vivre avec ça.
Merci pour vos contributions 🙂
OriginalL'auteur
Cet ancien relais de poste stills a besoin d'informations supplémentaires pour être complet. Il est évident qu'à l'origine le comportement souhaité ne peut être atteint, car l'opérateur = ne peut pas être surchargé, et de même C# ne peut pas être "trompé" dans le coulage d'un objet à son propre type... il va toujours se résument à une classe de référence de la mission. Mais Steffen en outre des postes de montrer à la classe Wrapper utilisé non pas seulement avec des variables locales, mais comme un champ de classe de type. Souhaité sémantique peut être utilisé ET l'intégrité du dictionnaire interne maintenue à l'aide des propriétés de la classe au lieu de champs publics.
Même en gardant l'original étant donné
Wrapper<T>
classe avec ses deux implicite opérateurs, voici le code qui fonctionne:Si ce changement était fait, il ne serait pas briser code existant car il permet néanmoins de différents modes de définition de la propriété:
Parce que ce n'est toujours pas la réponse à la question d'origine, l'utilisation de la classe Wrapper pourrait encore être problématique si utilisé à l'extérieur de la classe contexte de la propriété, c'est à dire passé entre l'objet, etc. Peut-être l'ensemble de la classe Wrapper pourraient être éliminés avec la bonne conception de classe, y compris l'utilisation de l'immeuble/accesseurs get.
OriginalL'auteur C Perkins