将对象强制转换为Type并使用方法

时间:2018-09-18 17:12:50

标签: c# inheritance casting

假设我有一个抽象类ObjectA。 ObjectC和ObjectB继承自ObjectA。从ObjectA继承的还有很多。

然后,我有一些根据对象类型执行某些操作的方法。

public void DoSomething(ObjectC data){}
public void DoSomething(ObjectB data){}

我想知道是否有一种方法可以根据对象的类型来调用所需的方法,这是因为我不知道我将得到哪种对象。

public void DoSomething(ObjectA data){
    DoSomething(data);
}

当前我正在使用

public void DoSomething(ObjectA data){
    if (data is ObjectB dataB){
        DoSomething(dataB);
    }else if (data is ObjectC dataC){
        DoSomething(dataC);
    }
}

我想知道是否有办法避免使用if/else

谢谢。

3 个答案:

答案 0 :(得分:4)

执行此操作的传统方法是反转您的要求,并使用virtual函数以@RuiJarimba在评论中描述的方式实现polymorphism。例如,考虑以下三个类(我将您的ObjectX类重命名为ClassX):

public abstract class ClassA
{
    public abstract void DoSomething();
}

public class ClassB : ClassA
{
    public override void DoSomething()
    {
        //Do something that is ClassB specific
    }
}

public class ClassC : ClassA
{
    public override void DoSomething()
    {
        //Do something that is ClassC specific
    }
}

ClassBClassC的每个实例本质上都是ClassA(通过继承)。 ClassBClassC都实现了DoSomething方法,该方法将覆盖ClassA定义的抽象定义。现在,我可以获取任何ClassA对象(由于ClassA是抽象的,因此必须是ClassA的子类的实例)并对其调用DoSomething()并获得DoSomething()的特定于类的实现。在下面的代码中,我创建了单独的实例。在现实生活中,通常会有ClassA对象引用的集合,您会逐步调用相应的方法:

   ClassA objectB = new ClassB();
   ClassA objectC = new ClassC();

   objectB.DoSomething();      //calls ClassB's version
   objectC.DoSomething();      //calls ClassC's version

这不是您要问的,但我想这就是您想要的。

继续上线

如果要保留相同的函数签名,可以将以下内容添加到ClassA定义中:

  public static void DoSomething<T>(T data) where T : ClassA
  {
      data.DoSomething();     //dispath through the right class using a virtual function
  }

如果您这样做,那么它将起作用(使用上面创建的objectBobjectC实例:

    ClassA.DoSomething(objectB);      //calls ClassB's version
    ClassA.DoSomething(objectC);      //calls ClassC's version

新代码的作用是获取传递的对象(它必须是ClassA子类的实例),然后简单地调用先前定义的虚函数,将事物分派到适当的类的实现。

答案 1 :(得分:1)

您可以使用is运算符和强制转换。 检出:

https://dotnetfiddle.net/uvjHHV

using System;

public class Program
{

    public abstract class ObjectA { }

    public class ObjectB : ObjectA {}

    public class ObjectC : ObjectA {}

    public static void Main()
    {
        // You may get this instance from anywhere
        Object o = new ObjectB();

        if (o is ObjectB) 
            DoSomething((ObjectB) o);
        else if (o is ObjectC)
            DoSomething((ObjectC) o);

    }


    public static void DoSomething(ObjectB o) {
        Console.WriteLine("Object B called");   
    }

    public static void DoSomething(ObjectC o) {
        Console.WriteLine("Object C called");   
    }
}

答案 2 :(得分:-1)

尝试使用接口。您可以使用相同的方法来处理多种类型。

using System;

namespace Demo
{
    class Program
    {
        interface IAwesomeInterface
        {
            void DoSomething(int number);
            void DoSomething(string strang);
            void DoSomething(Person person);
        }

        class MyClass : IAwesomeInterface
        {
            public void DoSomething(int number)
            {
                number = number + 100;
                Console.WriteLine(number);
            }

            public void DoSomething(string strang)
            {
                strang += " World";
                Console.WriteLine(strang);
            }

            public void DoSomething(Person person)
            {
                person.Id = person.Id++;
                person.Name += "Bar";

                Console.WriteLine($"{person.Id} - {person.Name}");
            }
        }

        static void Main(string[] args)
        {
            int someNumber = 3;

            string strang = "Hello";

            Person person = new Person();
            person.Id = 1;
            person.Name = "Foo";

            MyClass myClass = new MyClass();

            // Do something with a number
            myClass.DoSomething(someNumber);

            // Do something with a strang (string)
            myClass.DoSomething(strang);

            // Do something with a Person object
            myClass.DoSomething(person);

            Console.ReadKey();
        }
    }

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}