C# &引用;新";修饰符使基实现具有NULL属性值

C# &引用;新";修饰符使基实现具有NULL属性值,c#,.net,polymorphism,derived-class,C#,.net,Polymorphism,Derived Class,我试图使用多态性使派生类使用派生属性而不是基属性进行操作。我不知道如何用更清晰的语言来表达,所以这里有一个输出示例: // setup output to demonstrate the scenario static void Main(string[] args) { var foo = new Foo(); var foobase = foo as FooBase; Console.WriteLine("Foo is null? {0}",

我试图使用多态性使派生类使用派生属性而不是基属性进行操作。我不知道如何用更清晰的语言来表达,所以这里有一个输出示例:

// setup output to demonstrate the scenario
static void Main(string[] args)
{
    var foo = new Foo();            
    var foobase = foo as FooBase;

    Console.WriteLine("Foo is null? {0}", foo == null);
    Console.WriteLine("Foo.Bar is null? {0}", foo.Bar == null);
    Console.WriteLine("FooBase is null? {0}", foobase == null);
    Console.WriteLine("FooBase.Bar is null? {0}", foobase.Bar == null);
    Console.ReadLine();            
}

// base and derived.  These represent my problem.
class BarBase { }
class Bar : BarBase { }

// Base implementation using base properties
class FooBase
{
    public virtual BarBase Bar { get; set; }
    public FooBase() { }
}

// Derived implementation using "new" to operate with the 
// derived the property
class Foo : FooBase
{
    public new Bar Bar { get; set; }
    public Foo() : base()
    {
        // populate our modified property with the derived class
        Bar = new Bar();
        //base.Bar = Bar; // I don't want to do this, but how can I avoid it?
    }
}
输出:

Foo is null? False Foo.Bar is null? False FooBase is null? False FooBase.Bar is null? True Game.Camera is null? False SpecialChaseCameraMethod GameBase.Camera is null? False SpecialCameraBaseMethod Game.Camera is null? False SpecialFlightCameraMethod GameBase.Camera is null? True 有更好的办法吗?我错过了什么

提前谢谢


编辑(6/7/11)

给我的问题添加一个更具体的例子。基本上,游戏和相机都有抽象实现(这里非常基本…)。抽象游戏使用抽象摄影机进行基本工作。衍生游戏使用其衍生相机进行其专业工作。最后,我需要派生摄影机和抽象摄影机在各自的范围内工作

我已经给出了两个不同的摄像头实现和两个游戏实现(希望)来展示我所寻求的灵活性。请注意,Game1使用“黑客”来强制基础摄像头具有值-Game2不会这样做。Game1有我想要的行为,但没有我想要的实现

输出:

Foo is null? False Foo.Bar is null? False FooBase is null? False FooBase.Bar is null? True Game.Camera is null? False SpecialChaseCameraMethod GameBase.Camera is null? False SpecialCameraBaseMethod Game.Camera is null? False SpecialFlightCameraMethod GameBase.Camera is null? True 游戏。相机是空的吗?错误的 特殊相色谱法 游戏基地,摄像机是空的?错误的 特殊法 游戏。相机是空的吗?错误的 特殊摄影法 GameBase。相机为空?符合事实的
继承是实现这一点的最佳方法吗?

您需要使用
override
而不是
new

您仍然可以返回一个
对象,尽管它仍将返回为
BarBase
。但是当
Foo
对象被强制转换为
FooBase
时,
override
是确保使用
Foo
属性而不是
FooBase
属性的唯一方法

在这种情况下,泛型可能会有所帮助,主要是在
FooBase
类上:

class FooBase<T> where T: BarBase {
    public virtual T Bar { get; set; }
    public FooBase() { }
}

class Foo : FooBase<Bar> {
    public override Bar Bar { get; set; }
    public Foo() : base() {
        Bar = new Bar();
    }
}
泛型参数
T
BarBase
的约束意味着
FooBase
的任何子类都可以选择加入
BarBase
的任何子类,或者只处理
BarBase

class VagueFoo : FooBase<BarBase> { }
class-foo:FooBase{}

您需要使用
覆盖
而不是
新建

您仍然可以返回一个
对象,尽管它仍将返回为
BarBase
。但是当
Foo
对象被强制转换为
FooBase
时,
override
是确保使用
Foo
属性而不是
FooBase
属性的唯一方法

在这种情况下,泛型可能会有所帮助,主要是在
FooBase
类上:

class FooBase<T> where T: BarBase {
    public virtual T Bar { get; set; }
    public FooBase() { }
}

class Foo : FooBase<Bar> {
    public override Bar Bar { get; set; }
    public Foo() : base() {
        Bar = new Bar();
    }
}
泛型参数
T
BarBase
的约束意味着
FooBase
的任何子类都可以选择加入
BarBase
的任何子类,或者只处理
BarBase

class VagueFoo : FooBase<BarBase> { }
class-foo:FooBase{}
您可以尝试以下操作:将属性类型更改为BarBase并使用override。然后使用polimorphism将派生类Bar对象指定给BarBase属性。属性栏是虚拟的,因此将返回正确的对象


您可以尝试以下操作:将属性类型更改为BarBase并使用override。然后使用polimorphism将派生类Bar对象指定给BarBase属性。属性栏是虚拟的,因此将返回正确的对象

我要回答我自己的问题。事实上,有两个答案。可能还有很多其他的答案,但没有一个能找到答案

解决方案#1:并行层次结构

这个想法是由@Joel B Fant在早些时候的评论中提出的。我研究了ADO.NET是如何实现的(通过Reflector),并给出了一个实现。我对这种模式不感兴趣,因为它意味着同一系列对象具有多个属性——但这是一种合理的解决方案

(假设我的问题中的CameraBase、FlightCamera和ChaseCamera仍然定义为节省空间)

代码

// abstract game
abstract class GameBase
{
    public virtual CameraBase CameraBase { get; set; }
    public GameBase() { }
    public virtual void Play()
    {
        Console.WriteLine("GameBase.CameraBase is null? {0}", CameraBase == null);
        if (CameraBase != null)
            CameraBase.SpecialCameraBaseMethod();
    }
}

// awesome game using chase cameras
class Game1 : GameBase
{
    public override CameraBase CameraBase 
    { 
        get { return Camera; } 
        set { Camera = (ChaseCamera)value; } 
    }
    public ChaseCamera Camera { get; set; }
    public Game1()
    {
        Camera = new ChaseCamera();
    }
    public override void Play()
    {
        Console.WriteLine("Game.Camera is null? {0}", Camera == null);
        Camera.SpecialChaseCameraMethod();
        base.Play();
    }
}
// must inject the camera for this solution
static void Main(string[] args)
{
    new Game1(new ChaseCamera()).Play();
    Console.ReadLine();
}

// abstract game
abstract class GameBase
{
    public virtual CameraBase Camera { get; set; }
    public GameBase(CameraBase camera) // injection
    {
        Camera = camera;
    }
    public virtual void Play()
    {
        Console.WriteLine("GameBase.Camera is null? {0}", Camera == null);
        if (Camera != null)
            Camera.SpecialCameraBaseMethod();
    }
}

// awesome game using chase cameras
class Game1 : GameBase
{
    public new ChaseCamera Camera 
    { 
        get { return (ChaseCamera)base.Camera; } 
        set { base.Camera = value; } 
    }
    public Game1(ChaseCamera camera) : base(camera) { } // injection
    public override void Play()
    {
        Console.WriteLine("Game.Camera is null? {0}", Camera == null);
        Camera.SpecialChaseCameraMethod();
        base.Play();
    }
}
解决方案#2:继承、注入和扭转

这个“模式”可能有真名,但我不知道。它与并行层次结构(以及我的原始示例)非常相似,不同之处在于我通过构造函数注入摄影机,并使用基本属性(带强制转换)进行访问。我想我本可以避免注入,也可以直接赋值给基属性(但是为什么要避免注入呢?它太有用了!)。扭曲只是性能所需的铸造。它不干净,但也不难看。这是我目前首选的解决方案

代码

// abstract game
abstract class GameBase
{
    public virtual CameraBase CameraBase { get; set; }
    public GameBase() { }
    public virtual void Play()
    {
        Console.WriteLine("GameBase.CameraBase is null? {0}", CameraBase == null);
        if (CameraBase != null)
            CameraBase.SpecialCameraBaseMethod();
    }
}

// awesome game using chase cameras
class Game1 : GameBase
{
    public override CameraBase CameraBase 
    { 
        get { return Camera; } 
        set { Camera = (ChaseCamera)value; } 
    }
    public ChaseCamera Camera { get; set; }
    public Game1()
    {
        Camera = new ChaseCamera();
    }
    public override void Play()
    {
        Console.WriteLine("Game.Camera is null? {0}", Camera == null);
        Camera.SpecialChaseCameraMethod();
        base.Play();
    }
}
// must inject the camera for this solution
static void Main(string[] args)
{
    new Game1(new ChaseCamera()).Play();
    Console.ReadLine();
}

// abstract game
abstract class GameBase
{
    public virtual CameraBase Camera { get; set; }
    public GameBase(CameraBase camera) // injection
    {
        Camera = camera;
    }
    public virtual void Play()
    {
        Console.WriteLine("GameBase.Camera is null? {0}", Camera == null);
        if (Camera != null)
            Camera.SpecialCameraBaseMethod();
    }
}

// awesome game using chase cameras
class Game1 : GameBase
{
    public new ChaseCamera Camera 
    { 
        get { return (ChaseCamera)base.Camera; } 
        set { base.Camera = value; } 
    }
    public Game1(ChaseCamera camera) : base(camera) { } // injection
    public override void Play()
    {
        Console.WriteLine("Game.Camera is null? {0}", Camera == null);
        Camera.SpecialChaseCameraMethod();
        base.Play();
    }
}

这两种解决方案都为我提供了一个可接受的实施方案,达到了预期的效果。

我将回答我自己的问题。事实上,有两个答案。可能还有很多其他的答案,但没有一个能找到答案

解决方案#1:并行层次结构

这个想法是由@Joel B Fant在早些时候的评论中提出的。我研究了ADO.NET是如何实现的(通过Reflector),并给出了一个实现。我对这种模式不感兴趣,因为它意味着同一系列对象具有多个属性——但这是一种合理的解决方案

(假设我的问题中的CameraBase、FlightCamera和ChaseCamera仍然定义为节省空间)

代码

// abstract game
abstract class GameBase
{
    public virtual CameraBase CameraBase { get; set; }
    public GameBase() { }
    public virtual void Play()
    {
        Console.WriteLine("GameBase.CameraBase is null? {0}", CameraBase == null);
        if (CameraBase != null)
            CameraBase.SpecialCameraBaseMethod();
    }
}

// awesome game using chase cameras
class Game1 : GameBase
{
    public override CameraBase CameraBase 
    { 
        get { return Camera; } 
        set { Camera = (ChaseCamera)value; } 
    }
    public ChaseCamera Camera { get; set; }
    public Game1()
    {
        Camera = new ChaseCamera();
    }
    public override void Play()
    {
        Console.WriteLine("Game.Camera is null? {0}", Camera == null);
        Camera.SpecialChaseCameraMethod();
        base.Play();
    }
}
// must inject the camera for this solution
static void Main(string[] args)
{
    new Game1(new ChaseCamera()).Play();
    Console.ReadLine();
}

// abstract game
abstract class GameBase
{
    public virtual CameraBase Camera { get; set; }
    public GameBase(CameraBase camera) // injection
    {
        Camera = camera;
    }
    public virtual void Play()
    {
        Console.WriteLine("GameBase.Camera is null? {0}", Camera == null);
        if (Camera != null)
            Camera.SpecialCameraBaseMethod();
    }
}

// awesome game using chase cameras
class Game1 : GameBase
{
    public new ChaseCamera Camera 
    { 
        get { return (ChaseCamera)base.Camera; } 
        set { base.Camera = value; } 
    }
    public Game1(ChaseCamera camera) : base(camera) { } // injection
    public override void Play()
    {
        Console.WriteLine("Game.Camera is null? {0}", Camera == null);
        Camera.SpecialChaseCameraMethod();
        base.Play();
    }
}
解决方案#2:继承、注入和扭转

这个“模式”可能有真名,但我不知道。它与并行层次结构(以及我的原始示例)非常相似,不同之处在于我通过构造函数注入摄影机,并使用基本属性(带强制转换)进行访问。我想我本可以避免注入,也可以直接赋值给基属性(但是为什么要避免注入呢?它太有用了!)。扭曲只是性能所需的铸造。它不干净,但也不难看。这是我目前最喜欢的solu