简体   繁体   English

具有不同派生类型的属性的C#派生类

[英]C# Derived classes with properties of different derived types

Is there a way in C# to accomplish something like the following? C#中是否有一种方法可以完成以下任务? prop in each of the containers should be the same property, ie referencing prop from inside a childContainer should access the same object as code inside baseContainer. 每个容器中的prop应该具有相同的属性,即从childContainer内部引用prop应该访问与baseContainer中的代码相同的对象。

I want to be able to reference the property in functions within baseContainer while other code references the properties of the childContainers without needing to cast the property to the more specific class. 我希望能够在baseContainer中的函数中引用该属性,而其他代码则引用childContainers的属性,而无需将该属性强制转换为更特定的类。 I also need to be able to use prop when I only have a reference to an object of type baseContainer, regardless of what the actual type of the object is, ie I don't care if it's actually a derived type. 当我仅对类型为baseContainer的对象进行引用时,无论该对象的实际类型是什么,我也需要能够使用prop ,即我不在乎它是否实际上是派生类型。

I'm open to refactoring to use a different pattern if someone can suggest one. 如果有人可以提出建议,我愿意进行重构以使用其他模式。

    public class baseContainer
    {
        public basePropType prop {get; set;}
    }

    public class childContainer1 : baseContainer
    {
        public childProp1 prop {get; set;}
    }

    public class childContainer2 : baseContainer
    {
        public childProp2 prop {get; set;}
    }

    public class basePropType
    {
    }

    public class childProp1 : basePropType
    {
    }

    public class childProp2 : basePropType
    {
    }

    // elsewhere in another class
    baseContainer container = GetContainer(); // Don't know which child class this object actually is
    basePropType propVal = container.prop;

Hope this makes sense. 希望这是有道理的。

Context: The GetContainer() in the code sample was just an attempt to illustrate that I have a baseContainer ref that could reference an object of one of the derived classes. 上下文:代码示例中的GetContainer()只是为了说明我有一个baseContainer引用,该引用可以引用派生类之一的对象。 A simplification to try and make this readable without posting dozens of classes and masses of IP that my employer wouldn't really appreciate me posting :-) 一种简化的尝试,使之易于阅读,而无需发布数十种我的雇主不会真正欣赏我发布的IP的类和大量IP :-)

The real structure, involves a class creating an object of a either childContainer1 or childContainer2 (the real app has many more derived classes and may eventually have more classes derived from these, ie multiple levels of inheritance), and doing some processing, which relies on it being this specific type but then passes it onto multiple another services that don't care which specific classes are being used, they just handle the baseContainer. 真正的结构涉及一个类,该类创建childContainer1或childContainer2的对象(实际应用程序具有更多派生类,并且最终可能具有从这些派生类派生的更多类,即多个继承级别),并进行某些处理,这取决于它是这种特定类型,但随后将其传递给其他不在乎使用特定类的其他服务,它们仅处理baseContainer。

Not sure if this makes a difference to the solution but I've been asked for extra context. 不知道这是否对解决方案有所帮助,但有人要求我提供更多上下文。

Sure, you can achieve this with generics! 当然,您可以使用泛型来实现!

public class BasePropType { }
public class ChildProp1 : BasePropType { }
public class ChildProp2 : BasePropType { }

public abstract class BaseContainer<T> where T : BasePropType
{
    public T Prop { get; set; }
}

public class ChildContainer1 : BaseContainer<ChildProp1> { }
public class ChildContainer2 : BaseContainer<ChildProp2> { }

This can also be solved without generics, and using interfaces. 这也可以在没有泛型且使用接口的情况下解决。

public interface IBaseType { }
public class ChildProp1 : IBaseType { }
public class ChildProp2 : IBaseType { }

public abstract class BaseContainer
{
    protected BaseContainer(IBaseType type)
    {
        Prop = type;
    }

    public IBaseType Prop { get; private set; }
}

public class ChildContainer1 : BaseContainer
{
    public ChildContainer1()
     : base(new ChildProp1())
    {

    }
}

public class ChildContainer2 : BaseContainer
{
    public ChildContainer2()
     : base(new ChildProp2())
    {

    }
}

You can also use shadowing and casting to achieve this: 您还可以使用阴影和投射来实现此目的:

public class baseContainer
{
    public basePropType prop { get; set; }
}

public class childContainer1 : baseContainer
{
    public new childProp1 prop 
    {
        get => (childProp1)base.prop;
        set => base.prop = value;
    }
}

This has the overhead of a cast and the possibility of an invalid cast if for any reason the baseContainer sets prop to a value that is not of type childProp1 (which in your case is not supposed to happen as far as I understand the prerequisite). 如果baseContainer出于任何原因将baseContainer设置为不属于childProp1类型的childProp1 (根据我的理解,就您的情况而言,不应发生这种情况),这将具有baseContainer的开销和无效baseContainer的可能性。

Still the best way in my opinion is to use a new property to avoid the name-clash: 我认为,最好的方法还是使用新属性来避免名称冲突:

public class baseContainer
{
    public virtual basePropType prop { get; set; }
}

public class childContainer1 : baseContainer
{
    public childProp1 childProp { get; set; }

    public override basePropType prop 
    {
        get => childProp;
        set => (childProp1)childProp
    }
}

This avoids confusion about the different types of the (seemingly) same property and adds more type safety in case a wrong class could be assigned to the property. 这样可以避免对(看似)相同属性的不同类型感到困惑,并且可以在为该属性分配错误的类时增加类型安全性。

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

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