2013-12-14 105 views
3

9次出10,当我想要在字符串上使用Substring()方法,这是因为我想刮掉字符串的END,而不是开始的一些字符。虽然默认的子字符串确实支持这一点,但它通过获取第二个参数,即所需字符串的长度而不是端点来实现。这意味着如果我始终想要从一系列不同长度的字符串中删除N个字符,则必须执行额外的步骤,这可能会导致更多的代码。举个例子:修改字符串.Substring

//Shaving the first N chars 
string trimmed = foo.bar.widget.GetType().Name.Substring(N); 

//Shaving the last N chars 
string trimmed = foo.bar.widget.GetType().Name.Substring(0, foo.bar.widget.GetType().Name.Length - N); 

或可能以节省额外的函数调用,使用第二行:

string name = foo.bar.widget.GetType().Name; 
string trimmed = name.Substring(0, name.Length - N); 

无论哪种方式,你基本上翻倍从字符串末尾刮掉字符而不是开始字符所需的代码量。我的修改很简单。如果你传递一个否定的N(否则这将是毫无意义的),它会在字符串的末尾而不是开始处删除-N个字符。我已经可以用一个扩展方法的代码这件事:

public static string MySubstring(this string str, int val) 
{ 
    return (val > 0) ? str.Substring(val) : str.Substring(0, str.Length + val); 
} 

,然后当我要剃掉了最后一次加入正字符,我只是做:

string trimmed = foo.bar.widget.GetType().Name.MySubstring(-N); 

简短而亲切,就像削去开始的字符。我的问题是 - 是否可以重写默认的Substring()函数的行为,以便我可以做到这一点,而不必使用我自己的唯一名称的功能?这并不像它会使任何现有的代码无效,因为之前没有理由将它传递给一个负数,并且这样做只会引发异常和崩溃。这只是这些简单的没有任何意义的功能之一,它应该是开始实施时的一部分。

回答

4

根据C#文档,you can use extension methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called.所以答案是“否”。

可以说,这是一件好事™,否则您的代码将成为一个噩梦,读给不熟悉您的扩展名的人。

注:str.Substring(0, str.Length + val);可以str.Remove(str.Length + val)

+0

+1对于'Remove()'。它只保存了我的版本中的几个字符,但很高兴知道有一个为此目的而构建的函数。仍然认为我会使用扩展方法,因为这仍然要求我得到两次字符串,或者将它保存在本地变量中,就像在我的原始示例中一样。无论如何,链接到文档基本上给了我我的答案。可惜的是,原创并不是以这种方式开始工作的,因为它似乎是提供这两种方法的一个很好的简洁方法。 –

+1

@DarrelHoffman不允许负的字符串位置,因此需要使用不同的方法名称来指示意图的优点是增加了由错误计算位置引起的编程错误的可能性。缺点是非常有限:字符串算法很少需要从相同表达式的开始或结束位置指定位置。 –

+0

@TomBlodget但是你会看到一些字符串格式化表达式。就像旧式的C式'printf'函数一样,用于将文本与前导或尾随空格对齐,使用负值表示右对齐,正值表示左对齐。起初可能会引起混淆,但这是一种普遍的形式,它并非没有先例。 –

3

不能在字符串中的严格意义上的使用扩展方法重载的方法,因为编译器将始终选择一个实例方法在具有相同签名的扩展方法来代替编译方法调用时。但是,您可以使用命名参数来实现您想要的东西。这也应该有助于避免可读性问题。这里有一个例子

public static string Substring(this string @this, int trimFromEnd) 
{ 
    return @this.Substring(0, @this.Length - trimFromEnd); 
} 

// if you do 
"abc".Substring(1) -> returns "bc" 

// if you do 
"abc".Substring(trimFromEnd: 1) -> returns "ab" 

就个人而言,我觉得这一点比子串(-1)或仅仅子串(varName中),其中的varName恰好是负更具可读性。

+0

解决问题的甜蜜解决方法!这就是我喜欢的。 – NothingsImpossible

+0

把它称为'LeaveOff'作为一个专门的说明'IEnumberable'扩展方法与'Take'互补的游戏。尽管(或甚至由于)聪明地使用命名参数,重新使用'Substring'仍然令人困惑。 –

+0

嗯,它确实有效,但是每当你使用Intellisense时,它会令人讨厌地混淆(自动将参数改为无意义的“DataGridViewTriState”)。所以虽然它的确有窍门,但我认为我最好使用扩展方法的不同名称。尽管如此,聪明的解决方法还是+1。我可能会找到其他地方我可以使用该技巧。 –