当前位置:  开发笔记 > 编程语言 > 正文

直接投射vs'as'运算符?

如何解决《直接投射vs'as'运算符?》经验,为你挑选了8个好方法。

请考虑以下代码:

void Handler(object o, EventArgs e)
{
   // I swear o is a string
   string s = (string)o; // 1
   //-OR-
   string s = o as string; // 2
   // -OR-
   string s = o.ToString(); // 3
}

三种类型的铸造之间有什么区别(好吧,第三种不是铸造,但是你得到了意图).应该首选哪一个?



1> Sander..:
string s = (string)o; // 1

如果不是,则抛出InvalidCastException.否则,分配给,即使是.ostringosonull

string s = o as string; // 2

分配nullsif o是不是a string或if ois null.因此,您不能将它与值类型一起使用(null在这种情况下,操作员永远不会返回).否则,分配os.

string s = o.ToString(); // 3

如果是,则导致NullReferenceException.无论什么类型,都会分配任何返回.onullo.ToString()so


使用1进行大多数转换 - 它简单明了.我倾向于几乎从不使用2,因为如果某些东西不是正确的类型,我通常会发生异常.我只看到需要这种返回null类型的功能,其中设计糟糕的库使用错误代码(例如,返回null =错误,而不是使用异常).

3不是强制转换,只是一个方法调用.当您需要非字符串对象的字符串表示时使用它.


RE:Sander实际上有另一个很好的理由使用它,它简化了你的检查代码(检查null而不是检查null和正确的类型)这很有用,因为很多时候你宁愿抛出一个自定义的异常.但盲目的呼声是坏的,这是非常正确的.
如果您的代码可能针对特定类型执行特定操作,但在其他情况下无效,则#2也很有用.
对于像你不知道输入类型的Equals方法这样的东西,#2很方便.但是,一般情况下,1是首选.虽然首选,但是当你只期望一个时,显然会使用类型系统限制为一种类型:)
RE:Anheledir实际上我在第一次通话后会为空.您必须使用显式转换函数来获取字符串的值.
您可以在显式定义时为值类型指定"null",例如:int?一世; string s ="5"; i = s为int; //我现在是5 s = null; i = s为int; //我现在是空的
一般的经验法则.使用`as`之后必须进行测试以查看它是否为"null".或者至少接受"null"作为有效输入的其他代码.也就是说,我经常使用`as`强制转换,我使用它的一个例子是一个接受`IEnumerable `的方法,但如果它也是一个`ICollection`,它可以预先分配一个动态大小的集合.`ICollection col =输入为ICollection; if(col!= null)something.Reserve(col.Count);`

2> Quibblesome..:

    当某些东西 绝对是另一件事时使用.

    当某些东西可能是另一件事时使用.

    当你不在乎它是什么时使用,但你只想使用可用的字符串表示.


这是对接受的答案的一个很好的补充.
您可以在最近使用Elvis(?。)来避免担心:obj?.ToString()

3> Blair Conrad..:

这真的取决于你是否知道是否o是一个字符串以及你想用它做什么.如果你的评论意味着o真的真的是一个字符串,我更喜欢直接(string)o演员 - 它不太可能失败.

使用直接强制转换的最大优点是,当它失败时,你会得到一个InvalidCastException,它会告诉你几乎出了什么问题.

使用as运算符,如果o不是字符串,s则设置为null,如果您不确定并且想要测试,这很方便s:

string s = o as string;
if ( s == null )
{
    // well that's not good!
    gotoPlanB();
}

但是,如果您不执行该测试,则稍后将使用s并抛出NullReferenceException.这些往往是比较常见和很多难以追查,一旦他们在野外发生了,因为几乎每行取消引用变量,可能会抛出一个.另一方面,如果你试图转换为值类型(任何基元或结构,如DateTime),你必须使用直接转换 - 这as将无效.

在转换为字符串的特殊情况下,每个对象都有一个ToString,所以如果o不是null,你的第三个方法可能没问题,你认为该ToString方法可能会做你想要的.


一个注意事项 - 您可以使用带有*nullable*值类型的`as`.IE`o as DateTime`不起作用,但`o as DateTime?`将......

4> Mark Cidade..:

如果您已经知道它可以转换为什么类型,请使用C样式转换:

var o = (string) iKnowThisIsAString; 

请注意,只有使用C风格的强制转换才能执行显式类型强制.

如果你不知道它是否是所期望的类型,你要使用它,如果它是,使用关键字:

var s = o as string;
if (s != null) return s.Replace("_","-");

//or for early return:
if (s==null) return;

请注意,因为不会调用任何类型转换运算符.如果对象不为null且本机为指定类型,则它将仅为非null.

使用ToString()获取任何对象的人类可读字符串表示形式,即使它不能转换为字符串.


关于类型转换运算符,这是一个有趣的小问题.我有几种类型,我已经创建了转换,但必须注意.

5> Glenn Slaven..:

使用FindControl方法时,as.net中的as关键字很好用.

Hyperlink link = this.FindControl("linkid") as Hyperlink;
if (link != null)
{
     ...
}

这意味着您可以对类型变量进行操作,而不必object像使用直接强制转换那样对其进行转换:

object linkObj = this.FindControl("linkid");
if (link != null)
{
     Hyperlink link = (Hyperlink)linkObj;
}

这不是一件大事,但它节省了代码行和变量赋值,而且它更具可读性



6> Sergio Acost..:

'as'基于'is',这是一个在运行时检查对象是否是polimorphycally兼容的关键字(基本上如果可以进行转换),如果检查失败则返回null.

这两个是等价的:

使用'as':

string s = o as string;

使用'是':

if(o is string) 
    s = o;
else
    s = null;

相反,c风格的强制转换也是在运行时进行的,但是如果无法进行强制转换则抛出异常.

只是添加一个重要的事实:

'as'关键字仅适用于引用类型.你做不到:

// I swear i is an int
int number = i as int;

在这些情况下,你必须使用铸造.



7> Joel in Gö..:

图2对于转换为派生类型是有用的.

假设a是动物:

b = a as Badger;
c = a as Cow;

if (b != null)
   b.EatSnails();
else if (c != null)
   c.EatGrass();

会得到一个用最少的铸件美联储.


但是对于这种类型的问题最好使用多态性...
@Chirs Moutray,这并不总是可行,特别是如果它是一个图书馆.

8> Brady Moritz..:

根据在此页面上运行的实验:http : //www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as

(此页面有时会显示一些“非法引荐来源网址”错误,因此请刷新一下)

结论是,“ as”运算符通常比强制转换更快。有时快很多倍,有时快一点。

我个人认为“ as”也更易读。

因此,由于它既更快又更“安全”(不会抛出异常),并且可能更易于阅读,所以我建议始终使用“ as”。

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有