C# 中变量的多态性

本文关键字:多态性 变量 | 更新日期: 2023-09-27 18:32:30

有没有办法在C#中实现变量的多态性?

基本上我想写这样的东西:

public class BaseClass
{
}
public class FinalClass : BaseClass
{
}
public class A
{
   public BaseClass BaseClassProperty {get; set;}
}
public class B : A
{
   public override FinalClass BaseClassProperty {get; set;}
}

我确实知道泛型,但我认为这并不总是一个好的解决方案,因为您最终可能会得到这样的东西 -

 public class A<T,V,C>
 {
    public T TValue;
    public V VValue;
    public C CValue;
 }

我也知道关键字"新",但我觉得它太"俗气"。

编辑:我将解释我的情况以避免XY问题。

public abstract class BaseGameManager
{
    public BaseAccount account;
}                         
public abstract class BaseAccount
{
}
public class GameManager : BaseGameManager
{
    public Account account;
}                         
public class Account : BaseAccount
{
}

有时,我会将我的对象引用为 GameManager,有时引用为 BaseGameManager。当我将其引用为游戏管理器时,我不想每次都将帐户属性强制转换为帐户类。这是我的问题。我说泛型太多了,因为 account 不会是继承我描述的方式的唯一属性。

C# 中变量的多态性

我确实知道泛型,但我认为这并不总是一个好的解决方案,因为您最终可能会得到这样的东西

嗯,这是一个完美的解决方案。如果要动态键入类,则泛型是要走的路。

您类A只需要一个泛型类型参数,这对我来说似乎并不多。我有一些非常核心的基类,它们有很多泛型类型参数,而且使用起来比没有它要容易得多。

建议的代码:

public class A<BC> where BC : BaseClass
{
   public BC BaseClassProperty {get; set;}
}
public class B : A<FinalClass>
{ }

不,你不能做像你的A/B示例这样的事情。以下是为什么它不起作用的示例:

A actuallyA = new A();
A actuallyB = new B(); // Totally legal
actuallyA.BaseClassProperty = new BaseClass();
actuallyA.BaseClassProeprty = new FinalClass();
actuallyB.BaseClassProperty = new FinalClass(); // What B allows
// Because actuallyB is referenced locally as an A, that definition would allow it,
// however this would fail because B only allows the one base type.
actuallyB.BaseClassProperty = new BaseClass();
你想要

的违反了Liskov替换原则:

var x = new B();
A a = x;  // works, because B is a subtype of A
// Compiles, since BaseClassProperty is of type BaseClass,
// but fails, since B only accepts a FinalClass.
a.BaseClassProperty = new BaseClass();

因此,不,您的示例所演示的"变量多态性"在 LSP 成立的任何语言中都是合法的。当然,其他类型的多态性(例如,BA<FinalClass>的子类)是可能的。

您可以非常轻松地完成这项工作,但是,您需要使用"俗气"new

class Program
{
    static void Main(string[] args)
    {
        A a = new B();
        a.Prop = new MyBase();
        Console.WriteLine("'{0}'", a.Prop); // 'classtest.MyBase'
        Console.WriteLine("'{0}'", ((B)a).Prop); // ''
        a.Prop = new Final();
        Console.WriteLine("'{0}'", a.Prop); // 'classtest.Final'
        Console.WriteLine("'{0}'", ((B)a).Prop); // 'classtest.Final'
    }
}
public class MyBase
{
}
public class Final : MyBase
{
}
public class A
{
    public MyBase Prop { get; set; }
}
public class B : A
{
    public new Final Prop
    {
        get { return base.Prop as Final; }
        set { base.Prop = value; }
    }
}

如果你只需要在 A 和 b 中公开的 getter,你可以做这样的事情。

public class BaseClass
{
}
public class FinalClass : BaseClass
{
}
public class A
{
    private BaseClass baseProp;
    public virtual BaseClass BaseClassProperty {get { return baseProp; } }
}
public class B : A
{
    private FinalClass finalProp;
    public override BaseClass BaseClassProperty {get { return finalProp; } }
}