检查课程的最佳方式

时间:2009-01-26 19:12:00

标签: c#

我有一个方法,它接受一个参数是一个接口对象

像这样

private void SomeMethod(InterfaceA IUA)

在方法内部我有这样的声明

ClassD someVar = (ClassD)(((ClassC)((ClassB)IUA)).D);

一切都很精致和花花公子。但是,在某些情况下,对象IUA可能是ClassZ的实例而不是ClassB。所以在这种情况下上面的行错误了。在执行上述语句之前,有没有办法找出对象真正属于哪个类?如果我事先知道那么我可以有一个If语句并执行以下操作

ClassZ someVar = (ClassD)(((ClassC)((ClassZ)IUA)).Z);

我来自java背景...在java中我知道我们有getClass()...在.net中会有什么相同的东西?

10 个答案:

答案 0 :(得分:7)

真的不应该在没有充分理由的情况下编写这样的代码。

说:你可以使用is

if (a is ClassB)
{
    ClassB b = (ClassB)a;
}
else if (a is ClassZ)
{
    ClassZ z = (ClassZ)a;
}

...或as

ClassB b = a as ClassB;
if (b != null)
{
    // ...
}

答案 1 :(得分:6)

嗯,对于初学者来说,除非你有真的这样做的好理由,否则你不应该从接口转向课堂。如果您需要ClassD功能,那么您的方法应该接收ClassD,而不是InterfaceA。

让我感到困惑的另一件事是多重转型。我同时使用Java和C#,我从未见过像这样做多重演员的需要。

最后,您可以使用运算符“is”来查明某些类型是从某个类继承还是实现某个接口,如

if (IUA is ClassD)
{
    // do something
}

答案 2 :(得分:1)

你可以做到

if (someVar is ClassZ)

如果someVar是-A ClassZ,则返回TRUE,

someVar.GetType ()

获得实际的课程

答案 3 :(得分:1)

怎么样

if(IUA is ClassB)
  someVar = (IUA as ClassB).B;
elseif (IUA is ClassZ)
  someVar = (IUA as ClassZ).Z;

这应该有效,尽管你得到强制责骂这是一个相当糟糕的架构。

答案 4 :(得分:1)

如果您要将其丢弃,通过界面有什么意义?您可能希望重新评估设计,因为这样的代码会破坏多态性的目的。 此外,你应该使用'是'来测试类型。既然你要转换对象,你应该使用'as'并测试null。

答案 5 :(得分:1)

好的,这里有几个不同的选择:

  • Java的getClass()的等价物是GetType();您可以使用typeof(...)检索编译时所知类型的Type对象。这不是测试事物的最佳方式,除非你对确切的平等感兴趣。

  • Java的instanceof运算符的等价物是C#中的is运算符:

    if (x is SomeType) ...
    

    这也可以与盒装值一起使用来检查值类型:

    if (x is int) ...
    
  • 相关运算符是as运算符,它不返回true或false,而是指定类型的引用。类型必须是可空类型(引用或可空值类型),结果是原始值,但如果值是适当类型的引用,则强类型为目标类型,否则为null。例如:

    object x = "hello";
    
    string y = x as string; // y = "hello" now
    Stream z = x as Stream; // z = null now
    

    如果要检查引用是否属于特定类型,然后使用作为该类型的引用,则常见模式为:

    object x = GetObjectFromSomewhere();
    string y = x as string;
    if (y != null)
    {
        Console.WriteLine(y.Length); // Whatever
    }
    

    这比Java中所需要的更有效:

    object x = GetObjectFromSomewhere();
    if (x is string)
    {
        string y = (string) x;
        Console.WriteLine(y.Length); // Whatever
    }
    
  • 如果引用的错误是错误类型的错误,只需强制转换 - 如果你有一个错误就会抛出异常,这几乎肯定是最好的行为方式。那一点。

答案 6 :(得分:0)

我认为没有必要将IUA转换为ClassB。就我所知,你没有使用任何ClassB方法。

答案 7 :(得分:0)

您可以执行类似

的操作
If (IUA is ClassB)
    //I am class b

但是,鉴于您的方法正在使用接口,如果您希望回到实际的具体类型,我会质疑您的设计。您可以重新考虑创建一个可用于执行该方法操作的接口方法。

答案 8 :(得分:0)

来自MSDN:

 public static void Test (object o) 
   {
      Class1 a;
      Class2 b;

      if (o is Class1) 
      {
         Console.WriteLine ("o is Class1");
         a = (Class1)o;
         // do something with a
      }

      else if (o is Class2) 
      {
         Console.WriteLine ("o is Class2");
         b = (Class2)o;
         // do something with b
      }

      else 
      {
         Console.WriteLine ("o is neither Class1 nor Class2.");
      }
   }

答案 9 :(得分:0)

你应该使用方法重载,它应该是这样的:

private void SomeMethod(ClassB obj) {
  DoMoreStuff(obj.B);
}
private void SomeMethod(ClassZ obj) {
  DoMoreStuff(obj.Z);
}
private void  DoMoreStuff(int val) {
 // ..
}