铸造一个基本类型的派生类型的一种方法(A way of casting a base type to

2019-06-18 04:30发布

我不知道这是否是做还是不做一个奇怪的东西,或者如果它是一些如何代码味道......但我不知道是否有办法(某种接力模式将是很好),以“铸”一个基本类型其派生类型的形式。 我知道这是没有意义的派生类型将有额外的功能,家长不提供这是其自我本质上并不健康。 但是,有一些方法来做到这一点? 下面是一个代码示例这样我就可以更好地解释我的“M问。

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());
}

我知道这似乎是愚蠢的,但有什么办法来完成这一类的东西吗?

Answer 1:

不香,在“管理”的语言。 这是向下转型 ,并有处理一下,整整你所说的原因,任何理智的一路下跌(子类,提供超过基类-在哪里呢这个“更”是从哪里来的?)。 如果你真的想为一个特定的层次结构类似的行为,你可以使用构造函数派生类型将采取基本类型为原型。

人们可以建立与反思的东西,处理简单的情况下(即没有叠加状态更具体的类型)。 在一般情况下,只是重新设计来避免此问题。

编辑:Woops,不能写入碱/派生类型之间的转换运算符。 微软的一个怪胎试图“保护你”对付自己。 不错啊,至少他们没有在附近那样糟糕太阳。



Answer 2:

尝试组成,而不是继承!

在我看来,像你这样会更好传递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);
}

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

通过成分组成的代码重用提供了另一种方式,为苹果重用水果的实施剥离的()。 相反,延长水果,苹果可以坚持一个水果实例的引用和定义,简单地调用了果皮()自身的剥离()方法。



Answer 3:

我个人不认为这是值得在这种情况下使用继承的麻烦。 而不是仅仅通过基类实例在构造函数和访问它通过一个成员变量。

private class ExtendedClass //: BaseClass - like to inherit but can't
{
    public readonly BaseClass bc = null;
    public ExtendedClass(BaseClass b)
    {
        this.bc = b;
    }

    public int ExtendedProperty
    {
        get
        {
        }
    }
}


Answer 4:

向下转换是有道理的,如果你有派生类的对象,但它是由基类的参考,由于某种原因你想让它回到一个派生类类型引用引用引用。 换句话说,你可以垂头丧气扭转以往向上转型的效果。 但不能有由派生类型的引用所引用的基类的对象。



Answer 5:

我不是说我推荐这个。 但是,你可以把基类成JSON字符串,然后将其转化为派生类。

SomeDerivedClass layer = JsonConvert.DeserializeObject<SomeDerivedClass>(JsonConvert.SerializeObject(BaseClassObject));


Answer 6:

不,这是不可能的。 在如C#托管语言,它只是将无法正常工作。 运行时不会允许它,即使编译让它通过。

你说你自己,这似乎是愚蠢的:

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

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

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



Answer 7:

C#语言不允许这样的运营商,但你仍然可以写他们和他们的工作:

[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Implicit(Base a) { ... }

[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Explicit(Base a) { ... }


Answer 8:

是的 - 这是一个代码的气味,几乎指甲下来的事实,你的产业链出现断裂。

(从有限的样本)是你宁愿DerivedClass上SomeBaseClass的实例操作-让“DerivedClass SomeBaseClass”,而不是“DerivedClass 是一个 SomeBaseClass”。 这被称为“在继承青睐组成”。



Answer 9:

正如其他人所指出的那样,你的建议铸件是不是真的有可能。 难道也许是其中的情况下, Decorator模式可以推出(深入浅出提取物)?



Answer 10:

你有没有想过,什么是目前你的基类和派生类都将实现一个接口? 我不知道你为什么要实施这样的细节,但它可能工作。



Answer 11:

这就是所谓的向下转换和Seldaek的建议,使用“安全”的版本是健全的。

这里有一个相当不错的描述,代码样本 。



Answer 12:

因为你打算怎么得到“额外”的派生类这是不可能的。 编译器怎么会知道你的意思derivedClass1而不是derivedClass2当实例呢?

我想你真正需要的是工厂模式或类似这样你就可以实例化对象没有真正知道就是BEING实例化显式类型。 在你的榜样,具有“插入”的方法将是该实例的工厂返回实现的接口。



Answer 13:

我不知道为什么没有人说这一点,我可能错过的东西,但你可以使用as关键字,如果你要做一个if语句的使用,如果。

SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass
if(class is SomeDerivedClass)
    ;

CNC中我问这个问题很久以前



Answer 14:

我最近一直在必要性,以便把它的一些更多的属性与派生类型延伸的简单的DTO的。 然后我想重用一些转换逻辑我不得不从内部数据库类型的DTO的。

我解决的办法是通过执行对DTO类一个空的构造,使用这样的:

class InternalDbType {
    public string Name { get; set; }
    public DateTime Date { get; set; }
    // Many more properties here...
}

class SimpleDTO {
    public string Name { get; set; }
    // Many more properties here...
}

class ComplexDTO : SimpleDTO {
    public string Date { get; set; }
}

static class InternalDbTypeExtensions {
    public static TDto ToDto<TDto>(this InternalDbType obj) where TDto : SimpleDTO, new() {
        var dto = new TDto {
            Name = obj.Name
        }
    }
}

转换成复杂的一个时,我可以然后从简单DTO重用转换逻辑。 当然,我将不得不填补了一些其他方式的复杂类型的属性,但与简单的DTO的很多很多的特性,这确实简化了的东西IMO。



Answer 15:

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

最好的办法是用在这里的工厂方法。



Answer 16:

正如许多答案都指出,你不能垂头丧气这非常有意义。

然而,在你的情况, SomeDerivedClass没有将被“丢失”的特性。 所以,你可以创建一个这样的扩展方法:

public static T ToDerived<T>(this SomeBaseClass baseClass) 
    where T:SomeBaseClass, new()
{
    return new T()
    {
        BooleanEvaluator = baseClass.BooleanEvaluator,
        GetBaseClassName = baseClass.GetBaseClassName
    };
}

所以,你是不是铸造,只是转换:

SomeBaseClass b = new SomeBaseClass();
SomeDerivedClass c = b.ToDerived<SomeDerivedClass>();

这只有真正起作用的,如果所有的基类中的数据是可读可写性的形式。



Answer 17:

C ++处理使用构造它。 C ++类型转换 。 这似乎是一个监督我。 你们中许多人带来了什么将的过程中与额外的属性做的问题。 我会回答,什么是编译器做的时候它创建时,程序员不设置属性派生类? 我处理这种情况类似于C ++。 创建一个构造函数的基类然后手动在构造设置的属性。 这是绝对优选设置在派生类的变量和断裂的继承。 我也选择了它在一个工厂方法,因为我觉得最终代码会更干净外观。



文章来源: A way of casting a base type to a derived type