Home > Net >  C# cast non-generic class to generic base class regardless of type T
C# cast non-generic class to generic base class regardless of type T

Time:12-10

We want to convert a List<Rule> where we know they all derive from BuildingRule<T> into BuildingRule<T>, but the type T can be different.
We basically want to do _buildingRules.Find(x => ((BuildingRule<T>)x).GetBuilding(sku, upgradeId) != null)
(the `.GetBuilding() != null is a requirement the rule has to meet in order for it to be the right one).

Though this does not work, and we were wondering if there is a way to achieve what we are trying to do.

public abstract class Rule
{
    [XmlIgnore]
    public abstract string FileName { get; }
}

public abstract class BuildingRule<T> : Rule where T : BuildingDefinitionRule
{
    [XmlElement("Definition")]
    public virtual List<T> Definitions { get; set; }

    public virtual T GetBuilding(string sku, int upgradeId = 0)
    {
        return Definitions.Find(x => x.Sku == sku && x.UpgradeId == upgradeId);
    }
}

public abstract class BuildingRule : BuildingRule<BuildingDefinitionRule>
{
}```

CodePudding user response:

You can create non-generic BuildingRuleBase:

public abstract class BuildingRuleBase : Rule
{
    public abstract BuildingDefinitionRule GetBuilding(string sku, int upgradeId = 0);
}

And inherit it:

public abstract class BuildingRule<T> : BuildingRuleBase where T : BuildingDefinitionRule
{
    public override T GetBuilding(string sku, int upgradeId = 0)
    {
        return Definitions.Find(x => true);
    }
}

And make _buildingRules a collection of BuildingRuleBase.

Or look into using covariant generic interfaces:

public interface IBuildingRule<out T> where T : BuildingDefinitionRule
{
    T GetBuilding(string sku, int upgradeId = 0);
}

public abstract class BuildingRule<T> : Rule, IBuildingRule<T> where T : BuildingDefinitionRule
{
    [XmlElement("Definition")]
    public virtual List<T> Definitions { get; set; }

    public T GetBuilding(string sku, int upgradeId = 0)
    {
        return Definitions.Find(x =>true);
    }
}

With new List<IBuildingRule<BuildingDefinitionRule>>() for type of _buildingRules.

  • Related