简体   繁体   English

C#类类型转换

[英]C# Class Type conversion

This is such a difficult question to explain online but I shall try my best. 这是一个很难在线解释的问题,但我会尽力而为。 I have instantiated an object of type B which is stored in a variable of type A. I use the get type property, so now it is type B. Have I therefore performed an implicit conversion of type A and B. So therefore when a.show() is called is it of type B? 我实例化了一个类型为B的对象,该对象存储在类型为A的变量中。我使用get类型属性,所以现在它是类型B。因此我是否执行了类型A和B的隐式转换。 show()被称为类型B?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{

    class A
    {
        public virtual void show()
        {
            Console.WriteLine("Showing A");
        }

        public void test()
        {
            Console.WriteLine("called from A");
        }
    }

    class B:A
    {
        public override void show()

        {
            Console.WriteLine("Showing B");
        }

        public void testb()
        {
            Console.WriteLine("called from B");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {


            A a = new B();
            // Outputs ConsoleApplication.B
            Console.WriteLine("{0}", a.GetType());
            // outputs showing B
            a.show();
            // outputs called from A
            a.test();

            Console.ReadLine();
        }
    }
}

You haven't performed an implicit conversion as you haven't actually converted anything. 您尚未执行任何隐式转换,因为您实际上并未进行任何转换。

A a = new B();

You have directly instanciated an object of type B. You can reference it from a variable of type A because B is a sub class of A. However, the two actions should be considered as independant. 您已经直接实例化了B类型的对象。由于B是A的子类,因此可以从A类型的变量中引用它。但是,这两个操作应被视为独立的。

... = new B(); ... =新的B();

will always instanciate an object of type B, regardless of what is on the left. 不管左边是什么,将始终实例化类型B的对象。

A a = ...

Will always try to assign what is on the right to the variable a. 将始终尝试为变量a分配右侧的内容。

The only difference that the type of the reference will make is in how the object is seen by the CLR. 引用类型的唯一区别在于CLR看到对象的方式。

A a = new B();
B b = new B();

Both are objects of type B. However, 'a' will only allow you to work with it as if it were an object of type A. So, you can only call a.show() and a.test(), even although it is actually of type B and so does have the additional method testb(). 两者都是B类型的对象。但是,“ a”将只允许您像使用A类型的对象一样对其进行操作。因此,即使尽管,您也只能调用a.show()和a.test()。它实际上是B型,因此也有其他方法testb()。 'b' will allow you to call b.show(), b.test() and b.testb(). “ b”将允许您调用b.show(),b.test()和b.testb()。 Regardless of the variable type, when you call show(), it is of type b and so it is the overriden show() method that is returned. 无论变量类型如何,当您调用show()时,它的类型都是b,因此返回的是重写的show()方法。

Finally, what you can now do is downcast. 最后,您现在可以做的是垂头丧气。 ie you instanciated an object of type B so you can now cast it to a variable of type b and so allow full access to all of type B members. 即,您实例化了一个B类型的对象,因此现在可以将其强制转换为b类型的变量,从而允许完全访问所有B类型的成员。

eg: 例如:

A a = new B();
a.testb(); // this will not compile as a does not have a definition of testb().

A a = new B();
B b = (B)a; // downcast a to a reference of type B
b.testb(); // this is now fine

I just saw you additional question of why would you want to instanciate something as type A, ie the base class. 我刚刚看到了您另一个问题,为什么您要实例化类型A,即基类。 This is to provide a common ground as a way of working with objects of different types. 这是提供一个共同的基础,作为使用不同类型的对象的一种方式。 For example, you may have a base type of Animal and derrive from it several sub classes - Cat, Dog, Gerbil. 例如,您可能具有动物的基本类型,并从中破坏了几个子类-猫,狗,沙鼠。 However, you may then want to be able to pass a list of all Animals to a method that only needs to work with common properties. 但是,您然后可能希望能够将所有动物的列表传递给只需要使用公共属性的方法。 So, if Animal had a name, your List could be iterated and each Animals name referred to, even although Animal could itself be Abstract (Not able to be instanciated) and the list comprise entirely of Dogs, Cats and Gerbils. 因此,如果Animal具有名称,则即使Animal本身可以是Abstract(无法实例化)并且列表完全由Dog,Cat和Gerbils组成,也可以迭代您的List并引用每个Animals的名称。 You can also then downcast the various animals by finding out what there type is to interact with them further, eg 然后,您还可以通过找出与它们进行进一步交互的类型来淡化各种动物,例如

if (animal is Dog) {
    Dog dog = (Dog)animal;
}

Or you could use the 'as' keyword to do the cast: 或者,您可以使用'as'关键字进行强制转换:

Dog dog = animal as Dog;

Hope this helps. 希望这可以帮助。

Just because you store it in a variable of Type A, your variable still references an object of Type B. When you make calls on your variable "a", the CLR knows the correct method to call. 仅仅因为将其存储在类型A的变量中,您的变量仍然引用类型B的对象。当您对变量“ a”进行调用时,CLR知道正确的调用方法。 Since you overrode the show method, the show method of type B will be called. 由于您覆盖了show方法,因此将调用类型B的show方法。 But you didn't override test(), so the method implementation on type A is called. 但是您没有重写test(),因此调用了类型A上的方法实现。 This is possible because B "inherited" the test() behavior from A, but didn't override it. 这是可能的,因为B“继承”了A的test()行为,但没有覆盖它。

In your code: 在您的代码中:

 // outputs showing B
  a.show();

prints "Showing B" because show() is a virtual method. 打印showing B,因为show()是一个虚拟方法。 Any virtual method call is determined by the object type, not the type of the reference (late binding). 任何虚拟方法调用都取决于对象类型,而不是引用的类型(后期绑定)。 The reference a is pointing to an object of type B . 参考a指向类型B的对象。

  // outputs called from A
  a.test();

test() is simply inherited from class A and not a virtual method, so it prints "called from A". test()只是从类A继承而来,而不是虚拟方法,因此它打印“从A调用”。 The method call a.GetType() doesn't convert anything, it simply returns a instance of a Type-object. 调用a.GetType()的方法不会转换任何内容,它只是返回Type对象的一个​​实例。

Variable a points to an instance of type B , so no conversion is required in order for a.show() to the B.show() method. 变量a指向类型的实例B ,所以没有转换,以便需要a.show()B.show()方法。 That's precisely what virtual methods are supposed to do: call the method on the instantiated type (or the first implementation in the inheritance chain) that the variable references, not the declared type of the variable. 这正是虚拟方法应该做的:在变量引用的实例化类型(或继承链中的第一个实现)上调用方法,而不是变量的声明类型。

The call to a.test() won't do that because the method isn't declared virtual . 调用a.test()不会这样做,因为该方法未声明为virtual So it simply calls the A.test() method. 因此,它只是调用A.test()方法。

As mentioned in the other posts you have created an instance of type B but because you up-casted the object to type A you have the interfaces defined for type A. 如其他文章中所述,您已经创建了类型B的实例,但是由于将对象上载为类型A,因此您具有为类型A定义的接口。

If need to access to methods defined for type B you can down-cast the object to it's original type which gives you the definition for type B. 如果需要访问为B类型定义的方法,则可以将该对象向下转换为它的原始类型,从而为您提供B类型的定义。

for instance: 例如:

if (a is B)
{
    ((B)a).testb();
}

// or

B b = a as B;
if (b != null)
{
    b.testb();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM