因为DELPHI根深蒂固的缘故,以前看到关于"is"、"as"的资料总是一略而过,总以为它与DELPHI里是一样的东西,因为在.NET里与DELPHI一样的东西比较的多。
直到昨天看《.NET框架程序设计》才发现原来两者之间还是有区别的,这个区别直接直接导致了.NET与DELPHI在关于类型转换上的一些建议写法。
在DELHI下(代码乱写的,手边没有DELPHI),
type
A = class(tobject);
B = class(A);
var
instA:A;
instB:B;
begin
instA := B.create;
if (instA is B) then
instB := instA as B;
end;
《Delphi* 开发人员指南》以及很多资料上都说这样的写法,由于“as”要用到RTTI信息,比较影响性能,所以大多会给出下面的这种写法
if (instA is B) then
instB := B(instA);
当判断出可以转换之后直接用指针进行类型转换。
昨天看书才发现在.NET下,“is”还是那个“is”,但“as”已经不是原来那个“as”了。这里的“as”是不会抛出异常的,转换失败只是出来一个Null而已。
书不在身边,贴一段SDK文档:
The as operator is like a cast except that it yields null on conversion failure instead of raising an exception. More formally, an expression of the form:
expression as typeis equivalent to:
expression is type ? (type)expression : (type)nullexcept that
expression
is evaluated only once
也就是说,现在用实际上是“as”实际是集成了“is”与Type Cast了。
注意最后一句except that expression
is evaluated only once,也就是说虽然效果是等价的,但用“as”在效率上要好一点喽。
验证了一下:
namespace TypeCast
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
const int testcount = 500000000;
long tt;
A a = new B();
B b;
tt = DateTime.Now.Ticks;
for (int i = 0;i < testcount;i++){
if (a is B){
b = (B)a;
b.x = 1;
}
}
tt = DateTime.Now.Ticks - tt;
Console.WriteLine("test 'is' operator:{0}",tt.ToString());
tt = DateTime.Now.Ticks;
for (int i = 0;i < testcount;i++){
b = a as B;
if (b != null){
b.x = 1;
}
}
tt = DateTime.Now.Ticks - tt;
Console.WriteLine("test 'as' operator:{0}",tt.ToString());
Console.Read();
}
class A{
}
class B:A{
public int x;
}
}
}
结果:
test 'is' operator:115460267
test 'as' operator:68695354
的确快多了,差不多一倍。
看来还要好好看文档,
《.Net框架程序设计》这本书真不错。