Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 防止子类型使用父类型扩展方法_C# - Fatal编程技术网

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

C# 防止子类型使用父类型扩展方法,c#,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)

例如,我有几个扩展方法可以将字符串和对象转换为小数和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#只有object可以使用扩展方法而不能使用decimal、int等?你不能。这与其说是一个扩展方法问题,不如说是一个常规方法参数问题——当参数可以转换为方法参数类型时,它总是有效的

我能想到一些糟糕的黑客行为:

public static decimal ToDecimal<T>(this T value) where T : class, new()
publicstaticdecimaltodecimal(这个T值),其中T:class,new()
这将阻止您调用
ToDecimal()。ToDecimal()
因为
decimal
不是类;它还将阻止您调用
ToDecimal().ToString().ToDecimal()
,因为
string
没有无参数构造函数


老实说,我认为这并不是一个真正合适的扩展方法。我建议您在开始时要更加注意如何执行转换,并且只在非常合适的情况下执行转换。例如,您当前的扩展方法允许您在
double
decimal
之间进行不适当的转换,这不是一个好主意。在什么情况下你真的想这么做?您正在尝试转换哪些类型?

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

另一方面,他们有
IList
,其中已经有
Count
属性,并且不需要
Count()
扩展方法,该方法比
Count
属性效率低得多

他们不能禁止使用它,因此
IEnumerable
IList
的基本inetrface。 他们所做的是在
Count()
扩展方法中进行类型区分

大概是这样的:

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

我的建议是不要禁止任何东西,而是将最佳实现置于所有扩展方法之后。您可以分析扩展方法中的对象类型,并在转换为int时跳过十进制类型的
ToString()
,从而做出最佳反应。

我能想到的唯一方法是将扩展方法放在不同的命名空间中,并仅在需要时才包含它。当然,您仍然会在包含它的代码文件中遇到这个问题。我们当然也有同样的问题。现在我将试着写下我们的发现。我想如果我能限制这个方法只用于对象,应该没问题。否则,我同意这是不安全的。@Jake:就我个人而言,即使那样,我也会怀疑。您实际要转换的类型是什么?如果我必须选择一种类型,那么它将是string。但是很多都是从数据库中的对象开始的。@Jake:为什么有很多类型可以直接转换成十进制?我可以理解有许多具有十进制属性的类型,但那是另一回事。我也尽量避免字符串转换——在需要的地方,您应该考虑它们是否是来自用户的(在这种情况下,您应该使用他们的文化进行解析)或机器可读(在这种情况下使用不变的文化)。我的意思是从数据库中获取的值是类型对象,并在应用程序的整个生命周期中作为对象保留。业务要求每个字段可以是字符串或数字。当然,在“类对象”的意义上,这是没有意义的,但至少函数不是致命的。类型检查的另一个例子是
ToArray()
扩展方法在
IEnumerable
上的实现。顺便说一句,类型检查通常是一种不好的气味,但在这种情况下,我认为您应该为用户的方便做出妥协。