看看下面的代码,你能推断它显示的是什么吗?
namespace Chengbo {
public class MyClass {
public static void Main() {
Currency currency = new Currency(10, 50);
Console.WriteLine(currency);
Console.WriteLine("currency is " + currency);
Console.WriteLine("currency is (using ToString()) " + currency.ToString());
}
}
public struct Currency {
public uint Dollars;
public ushort Cents;
public Currency(uint dollars, ushort cents) {
this.Dollars = dollars;
this.Cents = cents;
}
public override string ToString() {
return string.Format("${0}.{1, -2:00}", Dollars, Cents);
}
public static implicit operator float(Currency value) {
return value.Dollars + value.Cents/100.0f;
}
}
}
显示如下
currency is $10.50
currency is (using ToString()) $10.50
Chengbo.MyClass.Main中有三个Console.WriteLine(),但是只有后面两个显示正确,怎么回事?
先看最后一个Console.WriteLine()语句,它显式调用了Currency.ToString()方法,所以可以确保Currency类以我们定义的、正确的形式显示。
第二个Console.WriteLine()语句没有显式调用Currency.ToString()方法,但是字符串"currency is"被传递到Console.WriteLine()方法,这让编译器认为整个参数都是字符串形式的,因此,Currency.ToString()方法被隐式地调用了。
现在来看看最特别的第一个Console.WriteLine()语句,这行代码只是简单的将未做任何变化的的Currency结构直接传递给Console.WriteLine()方法,Console.WriteLine()有很多种重载的形式,但是它却没有一个直接处理Currency结构的形式,所以编译器就开始尝试把Currency转化成一个合适的类型,让一个有匹配形式的Console.WriteLine()方法来处理它。如果我们察看MSDN文档,会发现Console.WriteLine()方法有一种高效显示float类型的重载形式,它需要的是一个float类型的参数,所以在这里,这种需要float类型参数的重载形式是最合适的,就像控制台显示的那样,我们提供的Currency转float的自定义转换被编译器隐式地调用了。
如果我们定义了一个拥有多个重载形式的方法,并且我们传递了一个没有匹配形式的参数给这个方法,那么我们就强迫编译器自己决定怎么转换数据来匹配一个合适的方法。编译器总是工作的很有逻辑,并且严格按照规则办事,但是结果却有可能不像我们期待的那样。如果有什么疑惑,最好指定一个显式的转化。