作为一个例子,我有几种扩展方法,用于将字符串和对象转换为小数和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等?
答案 0 :(得分:5)
你做不到。这不是一个扩展方法问题,而是一般的方法参数问题 - 当参数可以转换为方法参数类型时,它总是有效。
我可以想到一些难以理解的黑客行为:
public static decimal ToDecimal<T>(this T value) where T : class, new()
这会阻止您调用ToDecimal().ToDecimal()
,因为decimal
不是一个类;它也会阻止你调用ToDecimal().ToString().ToDecimal()
,因为string
没有无参数构造函数。
老实说,我建议它不是真的一个合适的扩展方法。我建议您更多地关注如何开始执行转换,并且只在非常合适的情况下执行转换。例如,您当前的扩展方法允许您不恰当地在double
和decimal
之间进行转换,这不是一个好主意。在什么情况下你真的想要这样做?您想要转换哪些类型?
答案 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()
来做出最佳反应。