对于`as`和`is`一个真正的应用(A real use for `as` and `is`)

2019-08-18 08:40发布

我已经-never-用as或者is在C#或支持关键字的任何语言。

你有什么用它来做什么?

我不意味我如何使用我的意思是你怎么样真的需要它?

我也逃离了相当大的C ++项目(我很自豪)这样做没有类型转换。

因此,考虑到我几乎从来没有强制转换,为什么我需要的关键字as或者is

Answer 1:

我不得不写代码来枚举所有放置在ASP.NET Web窗体控件和具体的控件执行特定操作,如添加背景颜色到所有文本框,等等。

最大的好处asis对我来说,我可以放心地检查变量是否是使用给定类型的is没有异常情况发生。 有一次,我敢肯定,这是一个给定类型的,我可以安全,轻松地将其转换为使用所需要的类型as

我基本上没有(简单!)是

foreach(Control c in form.Controls)
{
   if(c is Textbox)
      HandleTextbox(c as Textbox);

   if(c is Listbox)
      HandleListbox(c as Listbox);
}

等等。 如果没有asis这将是一个很大混乱,恕我直言。

基本上,你可能需要或可以好好利用的asis ,如果你与多态性处理很多-如果你有事情可以在我的示例页面上任意数量的类型,如控制列表。 如果你没有或不使用多态很多,你不可能遇到的那些运营商的需求。



Answer 2:

我用“作为”作为事件处理一个方便快捷获取发送对象回来时,我不知道在设计时的发送者。

protected void SomeButtonInAGridView_Click(object sender, EventArgs e)
{
    Button clickedButton = sender as Button;
}


Answer 3:

这里有一个很多出现:

class Foo {
     public override bool Equals(object obj)
     {
         // The more specific function needs to do null checking anyway.
         return Equals(obj as Foo);
     }

     public bool Equals(Foo obj)
     {
         // do some comparison here.
     }
}


Answer 4:

有趣的问题。 其实,我用他们所有的时间。 is很方便找出一个对象是否是某种类型的,我用的就是偶尔在仿制药或循环通过不同类型的对象。 这也是非常宝贵的与反思。

另外, as发现有更多的用途。 它往往是更安全的使用,然后正常投:当它失败时,它返回的不是一个异常空。 我也觉得它更清晰的语法和更容易使用它,检查返回值零,然后添加一个异常块。

基本上,我的意思是说,我喜欢这样的:

protected void GeneralEventHandler(object sender, EventArgs e)
{
    Button btn = sender as Button;
    if(btn != null)   // click came from a button!
        // do something
    else
        // other cases
}

还有这个:

protected void GeneralEventHandler(object sender, EventArgs e)
{
    if(sender is Button)   // click came from a button!
        // do something
    else
        // other cases
}

与此相反:

protected void GeneralEventHandler(object sender, EventArgs e)
{
    try 
    {
        Button btn = (Button) sender;
        // if we get this far, it's a button
    }
    catch(InvalidCastException ice)
    {
        // click did not come from a button! Handle other cases
    }
}

当然,这只是一个例子,但是当我能避免的try / catch,我会的。 这也让更多的空间真正的例外打通。



Answer 5:

我用它来清洁从获取数据DataReader ,可能是DBNull

int? personHeight = dr["Height"] as int?;

要么

int personHeight = dr["Height"] as int? ?? 0;


Answer 6:

下面是从埃里克利珀描述如何“为”在C#中使用一个帖子:

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

我所有的时间使用。 当我给拉了回来,从会话缓存序列化对象,我用,以确定序列化对象是存在的,正确的类型。 我能避免程序抛出一个错误,使用操作人员和检查空。 如果是空的,我知道缺少的东西,我可以重新创建对象,并把它推回缓存,下一次我需要它。

你可以通过完成强制转换运算符相同的结果,但增加了一个异常的开销,尤其是当你知道序列化的对象是不会在那里的部分时间。



Answer 7:

C#报价方式投用就是和运营商。 的是操作者检查对象是否与给定类型兼容,评价的结果是一个布尔值:真或假。 is运算符绝不会抛出异常。 下面的代码演示:

System.Object o = new System.Object();
System.Boolean b1 = (o is System.Object); // b1 is true.
System.Boolean b2 = (o is Employee); // b2 is false.

如果对象引用为null,因为没有可用的对象,以检查它的类型就是运营商始终返回false。

is运算符,通常使用如下:

if (o is Employee) {
Employee e = (Employee) o;
// Use e within the ‘if’ statement.
}

在这段代码中,CLR实际上是检查对象的类型两次:是运营商首先检查如果o是与员工类型兼容。 如果是,那么if语句里面,CLR再次验证Ø执行转换时,指的是员工。

C#提供了一种方法来简化这个代码,并通过提供作为运营商提高其性能:

Employee e = o as Employee;
if (e != null) {
// Use e within the ‘if’ statement.
}

在该代码中,CLR检查如果o是与雇员类型兼容,并且如果它是,作为返回一个非空指针到相同的对象。 如果o是不得与劳动者类型兼容,那么作为运营商返回null。



Answer 8:

如果你开发一个项目,提供了一个插件接口则asis很快就会成为你最好的朋友。



Answer 9:

这里还有一个用例进入卡里加里博士的小屋;-)

您可以链as运营商,如:

x = obj as Label as Control;

你为什么会做这样的事? 如果你想为空,如果它不是一个标签,但你要正确对待他们所有的控制。 只是投放文本框和标签直接控制会产生成功的两个,现在这将是空不想要的类型的控制。 这是你会不会经常需要一个快捷的方法,但偶尔得心应手。

对于相同的另一种用途是,当你需要ToString()的对象上,但只有当它是正确的类型,否则,你需要有一个默认的字符串。 这是我遇到的很多时候,ESP的情况。 与波苏斯。 因为ToString()是虚拟的,这工作:

// assume SomeClass has overridden ToString()
// return "none" if item is not of type SomeClass or if it is null to begin with
string itemText = (item as SomeClass as Object ?? "none").ToString();


Answer 10:

C-风格的转换(如(Foo)bar )将抛出InvalidCastException ,如果转换失败。 as ,在另一方面,将产生null (见本 )。 is操作者只是用于测试给定实例的运行时类型是否与所提供的类型(见兼容此 )。

is被广泛使用in.NET System.ComponentModel命名空间。 更具体地讲, 类型转换器 API在很大程度上依赖于is运营商以确定如何从一种类型转变为另一种。



Answer 11:

我在WinForms应用程序那里是编辑发票的GUI使用这两个关键字广泛,在各行ListView可能包含不同类型的项目(即,它可能是一个行项目或描述,或......)。 所有我放在项目ListView是源自ListViewItem ,所以再后来就当我去实现诸如编辑所选项目的事情,我必须检查哪些项目类型选择(使用is ),以显示相应的编辑界面。



Answer 12:

自定义类型转换器是第一位在脑海中。

public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
            {
                return GetEnumValue(myVal, (string)value);
            }
            if (value is Enum)
            {
                return GetEnumDescription((Enum)value);
            }
            return base.ConvertFrom(context, culture, value);
        }

第二来自哪里我有一个对象(用于跟踪的变化)的阴影是从基类继承的情况下

class BaseClass
{
    BaseClass _shadow;
}

protected override void UpdateShadow()
{
    ThisClass shadow = _shadow as ThisClass;
      //...
}


Answer 13:

如果你真的永远不必做铸造话,我很可能你就不会为这些运营商多大用处。 根据我的经验,但是,.NET编程呼吁了很多与设置的参数类型为“对象”代表打交道时,特别铸造的。 我认为,引入泛型有助于削减需要铸造,但它肯定是我很经常使用的东西。 我可能是“做错了”,但是,这只是我的经验。

所以,如果你打算做铸造反正我很喜欢的“是”,以提高代码的可读性运营商。 我宁愿看

if(foo is SomeType) {...}

然后

if(foo.GetType() == typeof(SomeType)) {...}


Answer 14:

marc_s的回答是一个小瑕疵,我看到这个代码,所有的时间,所以我想强调这些运营商之间的差异的重要性。 is是布尔测试,以确定对象是否是分配给一个特定类型。 as检查是否对象被分配给一个特定类型的,并且如果是,则返回该对象作为该类型,如果没有,它返回null。 marc_s的答案是真的这样做

foreach(Control c in form.Controls)
{
   if(c is Textbox)
      HandleTextbox(c is Textbox ? (Textbox)c : null);

   if(c is Listbox)
      HandleListbox(c is Listbox ? (Listbox)c : null);
}

它是多余的使用isas 。 无论你使用的时候as刚与上面的表达式替换它,就相当于。 使用is直接管型()as唯一本身。 一种更好的方式来写的例子是。

foreach(Control c in form.Controls)
{
   if(c is Textbox)
      HandleTextbox((Textbox)c); 
      //c is always guaranteed to be a Textbox here because of is 

   if(c is Listbox)
      HandleListbox((Listbox)c); 
      //c is always guaranteed to be a Listbox here because of is 
}

或者,如果你真的喜欢as

foreach(Control c in form.Controls)
{
   var textBox = c as Textbox;
   if(textBox != null) 
   {
       HandleTextbox(textBox);
       continue;
   }

   var listBox = c as ListBox
   if(listBox != null)
      HandleListbox(listBox);
}

我碰到的所有时间一个真实世界的例子从一个存储区,只有返回类型的对象获取对象。 缓存是一个很好的例子。

Person p;
if (Cache[key] is Person)
    p = (Person)Cache[key];
else 
    p = new Person();

我使用的as在真正的代码要少得多,因为它真的只适用于引用类型。 考虑下面的代码

int x = o as int;

if (x != null)
   ???

as失败,因为一个int不能为空。 is工作正常,虽然

int x;
if (o is int)
    x = (int)o; 

我相信也有这些运营商之间的一些速度差,但对于实际的应用中的差别可以忽略不计。



文章来源: A real use for `as` and `is`