繁体   English   中英

从派生类访问基类属性时避免转换

[英]Avoid casting when accessing base class properties from a derived class

作为C#的新手,我正竭尽全力地围绕用自己的方案进行铸造的最佳解决方案,基本上,我试图避免从派生类中铸造基类对象。

在我的GridManagerBase类中的示例中,GridTarget属性是由通用定义定义的,但是SelectedTarget使用的是基本接口,从GridManager类中继承该基本接口要求我强制转换以获得对其他属性的访问权限。

因此,我试图在不进行强制转换的情况下制定出一个干净的解决方案。

我在网上搜索了许多示例,但无法完全找到所需的答案,因此,确实需要任何建议。

非常感谢。

public class GridManager : GridManagerBase<IGridPoint>
{
    void DoWork()
    {
        var result = GridTarget.HasVehicle; // works

        var result2 = ((ITargetObject)SelectedTarget).SomeValue; // works with cast
    }
}

public abstract class GridManagerBase<TGridPoint> : IGridManagerBase<TGridPoint>
       where TGridPoint : class, IGridPointBase
{
    public TGridPoint GridTarget { get; protected set; }

    public ITargetObjectBase SelectedTarget { get; protected set; }

    //public IVehicleObjectBase SelectedVehicle { get; protected set; }
}

public interface IGridManagerBase<TGridPoint>
{
    TGridPoint GridTarget { get; }

    ITargetObjectBase SelectedTarget { get; }
}

public interface IGridPointBase
{
    int Row { get; }
}

public interface IGridPoint : IGridPointBase
{
    bool HasVehicle { get; }
}


public interface ITargetObjectBase
{
    int Row { get; set; }
}

public interface ITargetObject : ITargetObjectBase
{
    int SomeValue { get; }
}

更新好的,所以我的主要目标是拥有一个以上的GridManager,其他对象具有该GridManager的共同功能,因此我的想法是使用基本接口来实现这一目标。

从GridManager中,SelectedTarget(ITargetObjectBase)对象将具有通用逻辑,这很好,但是在GridManager中也具有唯一逻辑。

在问这个问题之前,我确实考虑过Prasanna建议的路线,应该提到这一点,这就是为什么我在IVehicleObjectBase中添加了注释,但是我不确定用于创建几个通用定义的指导原则。

我在具体的类中添加了一些其他代码,希望可以更好地了解我所从事的工作。

public class GridManager : GridManagerBase<IGridPoint>
{
    public GridManager()
    {
        GridTarget = new GridPoint();

        SelectedTarget = new TargetObject(1, 2);
    }

    public void DoWork()
    {
        var result = GridTarget.HasVehicle; // works

        var result2 = ((ITargetObject)SelectedTarget).SomeValue; // works with cast

        SelectedTarget.DoSomeCommonWork();
    }
}

public class GridManagerB : GridManagerBase<IGridPoint>
{
    public GridManagerB()
    {
        GridTarget = new GridPoint();

        SelectedTarget = new TargetObjectB(1, string.Empty);  
    }

    public void DoWork()
    {
        var result = GridTarget.HasVehicle; // works

        var result2 = ((ITargetObjectB)SelectedTarget).SomeOtherValue; // works with cast

        SelectedTarget.DoSomeCommonWork();
    }
}

public abstract class GridManagerBase<TGridPoint> : IGridManagerBase<TGridPoint>
       where TGridPoint : class, IGridPointBase
{
    public TGridPoint GridTarget { get; protected set; }

    public ITargetObjectBase SelectedTarget { get; protected set; }

    //public IVehicleObjectBase SelectedVehicle { get; protected set; }
}

public interface IGridManagerBase<TGridPoint>
{
    TGridPoint GridTarget { get; }

    ITargetObjectBase SelectedTarget { get; }
}

public interface IGridPointBase
{
    int Row { get; }
}

public interface IGridPoint : IGridPointBase
{
    bool HasVehicle { get; }
}


public interface ITargetObjectBase
{
    int Row { get; set; }

    void DoSomeCommonWork();
}

public interface ITargetObject : ITargetObjectBase
{
    int SomeValue { get; }
}

public interface ITargetObjectB : ITargetObjectBase
{
    string SomeOtherValue { get; }
}

public abstract class TargetObjectBase : ITargetObjectBase
{
    public int Row { get; set; }

    public TargetObjectBase(int row)
    {
        Row = row;
    }

    public void DoSomeCommonWork()
    {
        Console.WriteLine(Row.ToString());
    }
}

public class TargetObject : TargetObjectBase, ITargetObject
{
    public int SomeValue { get; private set; }

    public TargetObject(int row, int some)
        : base(row)
    {
        SomeValue = some;
    }
}

public class TargetObjectB : TargetObjectBase, ITargetObjectB
{
    public string SomeOtherValue { get; private set; }

    public TargetObjectB(int row, string other)
        : base(row)
    {
        SomeOtherValue = other;
    }
}

public class GridPoint : IGridPoint
{
    public int Row { get; set; }

    public bool HasVehicle { get; set; }
}

因此,我认为我最好的两个选择要么是走通用定义路线,要么是从GridManagerBase删除ITargetObjectBase属性,而在IGridManager接口中只有ITargetObject。

  • GridTarget不需要GridTarget类型IGridPoint的原因是:它是IGridPoint类型,直接包含HasVehicle的定义。
  • SelectedTarget的类型为ITargetObjectBase ITargetObjectBase不直接包含了定义SomeValue 因此,需要ITargetObjectITargetObject
  • 但是,在SelectedTarget.RowITargetObjectBase ,因为ITargetObjectBase包含Row定义。

在您的情况下,可以将IGridManagerBase为具有两个通用参数的类型,如下所示。 然后您可以在不进行强制转换的情况下调用SelectedTarget.SomeValue

public class GridManager : GridManagerBase<IGridPointA, ITargetObject>
{
    void DoWork()
    {
        var result = GridTarget.HasVehicle; // works
        var result2 = SelectedTarget.SomeValue; // works with cast
    }
}
public abstract class GridManagerBase<TGridPoint, TTargetObject> : IGridManagerBase<TGridPoint,TTargetObject> 
  where TGridPoint : class, IGridPointBase
  where TTargetObject : class, ITargetObjectBase
{
    public TGridPoint GridTarget { get; protected set; }
    public TTargetObject SelectedTarget { get; protected set; }
    //public IVehicleObjectBase SelectedVehicle { get; protected set; }
}
public interface IGridManagerBase<TGridPoint, TTargetObject>
{
    TGridPoint GridTarget { get; }
    TTargetObject SelectedTarget { get; }
}
public interface IGridPointBase
{
    int Row { get; }
}
public interface IGridPoint : IGridPointBase
{
    bool HasVehicle { get; }
}
public interface IGridPointA : IGridPointBase
{
    bool HasVehicle111 { get; }
}
public interface ITargetObjectBase
{
    int Row { get; set; }
}
public interface ITargetObject : ITargetObjectBase
{
    int SomeValue { get; }
}

暂无
暂无

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

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