C# 一种将基类型转换为派生类型的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/124336/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 14:40:22  来源:igfitidea点击:

A way of casting a base type to a derived type

提问by Adam Driscoll

I'm not sure if this is a strange thing to do or not, or if it is some how code smell...but I was wondering if there was a way (some sort of oop pattern would be nice) to "cast" a base type to a form of its derived type. I know this makes little sense as the derived type will have additional functionality that the parent doesn't offer which is in its self not fundamentally sound. But is there some way to do this? Here is a code example to so I can better explain what I"m asking.

我不确定这是否是一件奇怪的事情,或者它是否是代码的味道……但我想知道是否有一种方法(某种 oop 模式会很好)来“强制转换”基类型到其派生类型的一种形式。我知道这没有什么意义,因为派生类型将具有父级不提供的附加功能,而这些功能本身从根本上来说并不合理。但是有没有办法做到这一点?这是一个代码示例,以便我可以更好地解释我的要求。

public class SomeBaseClass {
    public string GetBaseClassName {get;set;}
    public bool BooleanEvaluator {get;set;}
}

public class SomeDerivedClass : SomeBaseClass {
    public void Insert(SqlConnection connection) {
          //...random connection stuff
          cmd.Parameters["IsItTrue"].Value = this.BooleanEvalutar;
          //...
    }
}

public static void Main(object[] args) {
    SomeBaseClass baseClass = new SomeBaseClass();
    SomeDerivedClass derClass = (SomeDerivedClass)baseClass; 
    derClass.Insert(new sqlConnection());
}

I know this seems goofy but is there any way to accomplish something of this sort?

我知道这看起来很傻,但是有什么办法可以完成这种事情吗?

采纳答案by Adam Wright

Not soundly, in "managed" languages. This is downcasting, and there is no sane down way to handle it, for exactly the reason you described (subclasses provide more than base classes - where does this "more" come from?). If you really want a similar behaviour for a particular hierarchy, you could use constructors for derived types that will take the base type as a prototype.

不健全,在“托管”语言中。这是downcasting,并且没有理智的方法来处理它,这正是您描述的原因(子类提供的不仅仅是基类 - 这个“更多”来自哪里?)。如果你真的想要一个特定层次结构的类似行为,你可以使用派生类型的构造函数,将基类型作为原型。

One could build something with reflection that handled the simple cases (more specific types that have no addition state). In general, just redesign to avoid the problem.

可以使用反射来构建一些处理简单情况(没有添加状态的更具体的类型)的东西。一般情况下,只需重新设计即可避免该问题。

Edit: Woops, can't write conversion operators between base/derived types. An oddity of Microsoft trying to "protect you" against yourself. Ah well, at least they're no where near as bad as Sun.

编辑:糟糕,不能在基/派生类型之间编写转换运算符。微软试图“保护你”对抗你自己的奇怪之处。嗯,至少他们不像 Sun 那样糟糕。

回答by leppie

That cannot work. Go look at the help page linked by the compile error.

那行不通。去看看编译错误链接的帮助页面。

The best solution is to use factory methods here.

最好的解决方案是在这里使用工厂方法。

回答by Ben Hoffstein

This is called downcasting and Seldaek's suggestion to use the "safe" version is sound.

这被称为向下转型,Seldaek 建议使用“安全”版本是合理的。

Here's a pretty decent description with code samples.

这是带有代码示例的相当不错的描述

回答by Maciej Hehl

Downcasting makes sense, if you have an Object of derived class but it's referenced by a reference of base class type and for some reason You want it back to be referenced by a derived class type reference. In other words You can downcast to reverse the effect of previous upcasting. But You can't have an object of base class referenced by a reference of a derived class type.

向下转换是有道理的,如果您有一个派生类的对象,但它被基类类型的引用引用,并且出于某种原因您希望它返回由派生类类型引用引用。换句话说,您可以向下倾斜以扭转先前向上倾斜的效果。但是您不能让派生类类型的引用引用基类的对象。

回答by Derek Park

No, this is not possible. In a managed language like C#, it just won't work. The runtime won't allow it, even if the compiler lets it through.

不,这是不可能的。在像 C# 这样的托管语言中,它是行不通的。运行时不会允许它,即使编译器允许它通过。

You said yourself that this seems goofy:

你自己说这看起来很傻:

SomeBaseClass class = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)class; 

So ask yourself, is classactually an instance of SomeDerivedClass? No, so the conversion makes no sense. If you need to convert SomeBaseClassto SomeDerivedClass, then you should provide some kind of conversion, either a constructor or a conversion method.

所以问问你自己,class实际上是一个实例SomeDerivedClass吗?不,所以转换没有意义。如果您需要转换SomeBaseClassSomeDerivedClass,那么您应该提供某种转换,构造函数或转换方法。

It sounds as if your class hierarchy needs some work, though. In general, it shouldn'tbe possible to convert a base class instance into a derived class instance. There should generally be data and/or functionality that do not apply to the base class. If the derived class functionality applies to allinstances of the base class, then it should either be rolled up into the base class or pulled into a new class that is not part of the base class hierarchy.

不过,听起来好像您的类层次结构需要一些工作。在一般情况下,它不应该是可能的一个基类实例转换成一个派生类的实例。通常应该有不适用于基类的数据和/或功能。如果派生类的功能适用于基类的所有实例,那么它要么被卷入基类,要么被拉入一个不属于基类层次结构的新类。

回答by Laplie Anderson

This is not possible because how are you going to get the "extra" that the derived class has. How would the compiler know that you mean derivedClass1 and not derivedClass2 when you instantiate it?

这是不可能的,因为您将如何获得派生类所具有的“额外”。当你实例化它时,编译器怎么知道你是指派生类1而不是派生类2?

I think what you are really looking for is the factory pattern or similar so you can instantiate objects without really knowing the explicit type that's being instantiate. In your example, having the "Insert" method would be an interface that instance the factory returns implements.

我认为您真正要寻找的是工厂模式或类似模式,这样您就可以实例化对象,而无需真正知道正在实例化的显式类型。在您的示例中,具有“插入”方法将是工厂返回的实例实现的接口。

回答by Mark Brackett

Yes - this is a code smell, and pretty much nails down the fact that your inheritance chain is broken.

是的 - 这是一种代码异味,并且几乎确定了您的继承链已损坏的事实。

My guess(from the limited sample) is that you'd rather have DerivedClass operate on an instance of SomeBaseClass - so that "DerivedClass has aSomeBaseClass", rather than "DerivedClass is aSomeBaseClass". This is known as "favor composition over inheritance".

我的猜测(来自有限的示例)是您宁愿让 DerivedClass 对 SomeBaseClass 的实例进行操作 - 这样“DerivedClass具有SomeBaseClass”,而不是“DerivedClassSomeBaseClass”。这被称为“优先组合而不是继承”。

回答by Rob Fonseca-Ensor

Try composition instead of inheritance!

尝试组合而不是继承!

It seems to me like you'd be better off passing an instance of SomeBaseClass to the SomeDerivedClass (which will no longer derive base class, and should be renamed as such)

在我看来,你最好将 SomeBaseClass 的一个实例传递给 SomeDerivedClass (它将不再派生基类,应该像这样重命名)

public class BooleanHolder{       
    public bool BooleanEvaluator {get;set;}
}

public class DatabaseInserter{
    BooleanHolder holder;

    public DatabaseInserter(BooleanHolder holder){
        this.holder = holder;
    }

    public void Insert(SqlConnection connection) {
          ...random connection stuff
          cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar;
          ...
    }
}

public static void Main(object[] args) {
    BooleanHolder h = new BooleanHolder();
    DatabaseInserter derClass = new DatabaseInserter(h);
    derClass.Insert(new sqlConnection);
}

Check out http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html(page 3):

查看http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html(第 3 页):

Code reuse via composition Composition provides an alternative way for Apple to reuse Fruit's implementation of peel(). Instead of extending Fruit, Apple can hold a reference to a Fruit instance and define its own peel() method that simply invokes peel() on the Fruit.

通过组合重用代码 Composition 为 Apple 提供了一种替代方法来重用 Fruit 的果皮实现。Apple 可以保留对 Fruit 实例的引用,而不是扩展 Fruit,并定义自己的 Peel() 方法,该方法只需在 Fruit 上调用果皮()。

回答by Boris Callens

As others have noted, the casting you suggest is not really possible. Would it maybe be a case where the Decorator pattern(Head First extract) can be introduced?

正如其他人所指出的,您建议的演员阵容实际上是不可能的。是否可以引入装饰器模式(Head First 摘录)?

回答by marr75

Have you thought about an interface that what is currently your base class and your derived class both would implement? I don't know the specifics of why you're implementing this way but it might work.

您是否考虑过当前基类和派生类都将实现的接口?我不知道您为什么以这种方式实施的具体细节,但它可能会奏效。