防止子类型使用父类型扩展方法

时间:2011-11-22 08:14:10

标签: c#

作为一个例子,我有几种扩展方法,用于将字符串和对象转换为小数和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 }

但我想阻止像这样的链接:

myobject.ToDecimal().ToDecimal();

甚至

myobject.ToDecimal().ToInt32();

如果程序员想要将小数转换为int32,那么我希望他使用Convert.ToInt32(),因为省略了Convert.ToString部分,它可能效率更高,而且还有更多功能。

如何告诉C#只有对象可以使用扩展方法而不是decimal,int等?

2 个答案:

答案 0 :(得分:5)

你做不到。这不是一个扩展方法问题,而是一般的方法参数问题 - 当参数可以转换为方法参数类型时,它总是有效。

我可以想到一些难以理解的黑客行为:

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

这会阻止您调用ToDecimal().ToDecimal(),因为decimal不是一个类;它也会阻止你调用ToDecimal().ToString().ToDecimal(),因为string没有无参数构造函数。

老实说,我建议它不是真的一个合适的扩展方法。我建议您更多地关注如何开始执行转换,并且只在非常合适的情况下执行转换。例如,您当前的扩展方法允许您不恰当地在doubledecimal之间进行转换,这不是一个好主意。在什么情况下你真的想要这样做?您想要转换哪些类型?

答案 1 :(得分:1)

同样的问题也是LINQ中的Microsoft。 在Count()上提供IEnumarable<T>方法。它迭代其中的整个序列计数元素。

另一方面,他们IList<T>已经拥有Count属性,并且不需要Count()扩展方法,这比Count属性效率低得多

他们无法禁止使用它,因此IEnumerable<T>IList<T>的基本界面。 他们所做的是在Count()扩展方法中进行类型区分。

这样的事情:

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

我的建议不是禁止任何东西,只是将最佳实现置于所有扩展方法之后。您可以分析扩展方法中的对象类型,并在转换为int时通过为小数类型滑动ToString()来做出最佳反应。