Abstraction empêchant l'utilisation de types personnalisés, quelles sont les règles à suivre dans une mise en œuvre?

StackOverflow https://stackoverflow.com/questions/4072301

Question

Je l'ai construit un typesystem personnalisé pour une utilisation dans les scripts C # dans une application. Les scripts sont compilés à la volée et permet l'interaction avec l'application des données internes. Ce typesystem est conçu d'une manière abstraite en utilisant des interfaces comme IValue. La mise en œuvre de IValue peut être un RefString, RefInteger, RefDouble (parmi beaucoup d'autres, mais cela suffit pour démontrer mon problème).

Nous arrivons maintenant au point où je suis bloqué ... L'utilisation de ces objets IValue est un peu contre nature. Il est considéré comme une bonne conception de toujours utiliser les interfaces pour interagir avec les objets, mais il n'y a pas possibilité de définir une conversion implicite ou la surcharge d'un opérateur pour les interfaces. Cela donne à des situations où la coulée explicite laid est inévitable pour que l'opérateur droit s'utilisé.

Exemple:

IValue Add(IValue a, IValue b)
{
    //return a+b; // won't work: which operator +() to use?
    return (RefInteger)a + (RefInteger)b;
}

Dans le cas de C # dans les expressions impliquant des types de valeur, les conversions implicites sont fournis. Ce qui est une bonne façon de concevoir un tel système personnalisé?

I réécrit le typesystem supprimant l'interface IValue et l'introduction d'une classe de base de RefValue. De cette façon, déjà une partie des moulages explicites pourrait être éliminé. Je mis en œuvre certaines de l'opérateur surcharge dans cette classe de base, mais qui a causé beaucoup de problèmes avec les opérateurs de conversion par défaut ... A côté de cela la logique de mettre en œuvre dans la mise en œuvre opérateur impliquants beaucoup de connaissances sur les types dans le système. Je pense que cela est en quelque sorte encore le chemin qu'il faut aller, mais quelles sont les règles à suivre pour mettre en œuvre ce dans un bon et de manière sûre?

EDIT : Après avoir lutté un certain temps, certaines des règles que je pouvais trouver sur sont:

  • Déclarer implicite que les opérateurs de conversion de types de base (int, double, chaîne, ...)
  • Déclarer explicitement les conversions à des types de base (pour éviter des conversions implicites à int !! ce qui se passe assez souvent, mais pourquoi?)
  • Pour éviter des appels ambigus le +, -, /, * les opérateurs ne devraient pas être surchargées dans la classe de base et dans les classes dérivées. [Quelle est la voie à suivre alors? Je l'ai fait l'opération de surcharge dans les classes dérivées, cela nécessite la coulée sur l'utilisation, ce qui est à nouveau laid ...]
Était-ce utile?

La solution

Si vous êtes censé être en mesure de faire une opération de Add sur tous IValues, peut-être l'interface devrait inclure une méthode Add? Ensuite, vous pouvez faire return a.Add(b);, et pousser la connaissance de la façon d'effectuer l'opération dans chaque type.

Un problème est que maintenant il semble, vous pourriez obtenir des appels où a est RefString et b est RefInteger, ce qui est sans doute pas ce que vous voulez. Génériques peuvent aider à résoudre que:

T Add<T>(T a, T b) where T : IValue
{
    return a.Add(b);
}

(Bien sûr, vous devrez ajouter une vérification nul et comme le cas échéant)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top