簡體   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