3 votes

Empêcher les types enfants d'utiliser les méthodes d'extension du type parent

À titre d'exemple, j'ai créé plusieurs méthodes d'extension pour convertir des chaînes de caractères et des objets en décimales et en int32.

    public static decimal ToDecimal(this object o)
    {
         return Convert.ToString(o).ToDecimal();
    }

    public static decimal ToDecimal(this string s)
    {
         decimal d = decimal.TryParse(s, out d) ? d : 0;
         return d;
    }

    public static Int32 ToInt32(this object o) { //etc }

Mais je veux éviter les enchaînements de ce type :

myobject.ToDecimal().ToDecimal();

ou même

myobject.ToDecimal().ToInt32();

Si le programmeur veut convertir la décimale en int32, je veux qu'il utilise Convert.ToInt32() qui est peut-être simplement plus efficace puisque la partie Convert.ToString est omise, et qui a également plus de fonctionnalités.

Comment puis-je dire à C# que seuls les objets peuvent utiliser la méthode d'extension et non les décimales, les int, etc.

5voto

Jon Skeet Points 692016

Vous ne pouvez pas. Il ne s'agit pas tant d'un problème de méthode d'extension que d'un problème général de paramètre de méthode - il sera toujours valide lorsque l'argument peut être converti dans le type de paramètre de la méthode.

Je peux penser à quelques solutions de contournement grotesques :

public static decimal ToDecimal<T>(this T value) where T : class, new()

Cela vous empêcherait d'appeler ToDecimal().ToDecimal() como decimal n'est pas une classe ; cela vous empêcherait également d'appeler ToDecimal().ToString().ToDecimal() como string n'a pas de constructeur sans paramètre.

Je dirais que ce n'est pas le cas vraiment une méthode d'extension appropriée, pour être honnête. Je suggérerais de faire plus attention à la façon dont vos conversions sont effectuées pour commencer, et de ne les faire que dans des situations très appropriées. Par exemple, votre méthode d'extension actuelle vous permettrait de convertir entre double y decimal de manière inappropriée, ce qui n'est pas une bonne idée. Dans quelles circonstances devez-vous vraiment veulent-ils le faire ? Quels sont les types de produits que vous essayez de convertir ?

1voto

achitaka-san Points 2591

Le même problème a également été rencontré par Microsoft dans LINQ. La fourniture Count() méthode sur IEnumarable<T> . Il itère la séquence entière en comptant les éléments qu'elle contient.

De l'autre côté, ils ont IList<T> qui ont déjà Count et n'a pas besoin de la propriété Count() qui est beaucoup plus inefficace que la méthode d'extension de la Count propriété.

Ils ne peuvent donc pas en interdire l'utilisation IEnumerable<T> est une interface de base de IList<T> . Ce qu'ils font, c'est qu'ils font une différenciation de type à l'intérieur Count() méthode d'extension.

Voici ce qu'il en est :

if (obejct is List) {return ((List)object).Count;}
else {...}

Mon conseil est de ne rien interdire mais de mettre en place des implémentations optimales pour toutes les méthodes d'extension. Vous pouvez analyser le type d'objet à l'intérieur de vos méthodes d'extension et réagir de manière optimale en sautant la case ToString() pour les types décimaux lorsqu'ils sont convertis en int.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X