6.1.2.1 在 C# 中模拟自定义运算符
在 C# 中,虽然可以重载现有的运算符,但是,不能声明新的运算符。然而,在某种程度上,使用扩展方法,可以实现相同的模式。扩展方法是 C# 3.0 中的一项新功能,下面我们简要介绍一下。
扩展方法(Extension methods)
在 C# 中,每个方法必须被包在类中,处理对象的操作是类声明的一部分,可以使用点表示法来调用方法。扩展方法为我们处理对象添加新方法,无需修改原始的类声明。以前,这可能要通过写静态方法才行,就像这样:
StringUtils.Reverse(str);
这是非常不现实的,因为,要在某些工具类中找到静态方法,是相当困难的。C# 3.0 中,我们可以把Reverse 实现为扩展方法,以这种方式调用:
str.Reverse();
实现扩展方法相当容易,因为,它就是有一个特别修饰符的普通静态方法,唯一的区别,是它可以作为实例方法来调用,使用点表示法;它仍然是静态方法,因此,它既不能添加新字段,也不能访问对象的私有状态:
static class StringUtils {
publicstatic string Reverse(this string str) { }
}
所有扩展方法都必须括在非嵌套的静态类中,且必须是静态方法;修饰符 this 放在第一个参数之前,告诉编译器为它是扩展方法。
如果我们把前面示例中字符串连接实现为扩展方法,得到的语法非常类似于原始的 F# 版本。清单 6.3 显示了使用标准的静态方法调用和扩展方法,写的同样代码。
清单 6.3 使用扩展方法处理字符串 (C#)
public static string AddLine(this stringstr, string next) {
returnstr + "\n>>" + next;
}
Console.WriteLine(
StringUtils.AddLine(
StringUtils.AddLine("Helloworld!", "How are you today"),
"I'mfine!"));
Console.WriteLine("Hello world!"
.AddLine("How are you today")
.AddLine("I'm fine!"));
纯粹根据可读性就能看出好处:我们能够写方法调用的顺序,与希望出现的顺序相同,而不需要指定实现方法的类,也不需要额外的大括号。这是常有的事,语法造成了重要差异。