[英]Avoid casting when accessing base class properties from a derived class
As a noob to C# I'm struggling to wrap my head around the best solution for casting with my scenario, basically I'm trying to avoid casting base class objects from a derived class. 作为C#的新手,我正竭尽全力地围绕用自己的方案进行铸造的最佳解决方案,基本上,我试图避免从派生类中铸造基类对象。
In my example within GridManagerBase class the GridTarget property is defined by the generic definition, but the SelectedTarget is using a base interface, which from with the GridManager class requires me to cast to gain access to additional properties. 在我的GridManagerBase类中的示例中,GridTarget属性是由通用定义定义的,但是SelectedTarget使用的是基本接口,从GridManager类中继承该基本接口要求我强制转换以获得对其他属性的访问权限。
So I'm trying to work out a clean solution without the casting. 因此,我试图在不进行强制转换的情况下制定出一个干净的解决方案。
I've searched many examples online and cant quite get the answer I'm looking for, so looking for any advice really. 我在网上搜索了许多示例,但无法完全找到所需的答案,因此,确实需要任何建议。
Many thanks. 非常感谢。
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; }
}
UPDATE Ok, so my primary goal is to have more than one GridManager from which other objects have common functionality, so my thought was to use base interfaces to achieve this. 更新好的,所以我的主要目标是拥有一个以上的GridManager,其他对象具有该GridManager的共同功能,因此我的想法是使用基本接口来实现这一目标。
From the GridManager the SelectedTarget (ITargetObjectBase) object will have common logic, which is fine, but unique logic also at the GridManager. 从GridManager中,SelectedTarget(ITargetObjectBase)对象将具有通用逻辑,这很好,但是在GridManager中也具有唯一逻辑。
I did think about going the route suggested by Prasanna prior to me asking the question, should have mentioned that, kinda why I left the IVehicleObjectBase commented in, but I'm not sure what guidelines there are for the creating several generic definitions. 在问这个问题之前,我确实考虑过Prasanna建议的路线,应该提到这一点,这就是为什么我在IVehicleObjectBase中添加了注释,但是我不确定用于创建几个通用定义的指导原则。
I've added some additional code with concrete classes tho hopefully give a better idea what I'm on about. 我在具体的类中添加了一些其他代码,希望可以更好地了解我所从事的工作。
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; }
}
So I think my best two options are either to go the generic definition route or to remove the ITargetObjectBase property from GridManagerBase and just have ITargetObject within an IGridManager interface. 因此,我认为我最好的两个选择要么是走通用定义路线,要么是从GridManagerBase删除ITargetObjectBase属性,而在IGridManager接口中只有ITargetObject。
GridTarget
is that: it is of type IGridPoint
which directly contains the definition for HasVehicle
. GridTarget
不需要GridTarget
类型IGridPoint
的原因是:它是IGridPoint
类型,直接包含HasVehicle
的定义。 SelectedTarget
is of type ITargetObjectBase
. SelectedTarget
的类型为ITargetObjectBase
。 ITargetObjectBase
does not directly contain the definition for SomeValue
. ITargetObjectBase
不直接包含了定义SomeValue
。 So a cast to ITargetObject
is needed. ITargetObject
为ITargetObject
。 SelectedTarget.Row
as ITargetObjectBase
contains definition for Row
. SelectedTarget.Row
中ITargetObjectBase
,因为ITargetObjectBase
包含Row
定义。 In your case, you could make IGridManagerBase
into a type with two generic parameters, as shown below. 在您的情况下,可以将
IGridManagerBase
为具有两个通用参数的类型,如下所示。 Then you could call SelectedTarget.SomeValue
without a cast 然后您可以在不进行强制转换的情况下调用
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.