用泛型继承类中的实现添加

时间:2010-09-03 19:47:31

标签: c# generics inheritance language-features

结构......

abstract class Unit
{
 int Id;
}

class Measure : Unit
{
 int Current;
 int Baseline;
}

class Weight : Unit
{
 int Minimum;
 int Maximum;
 int Current;
}

我基本上想添加一个“添加”方法,用于将两个度量添加到一起,或者将两个权重一起添加。但它需要在Unit基类中。所以基本上如果我有

List<Units> units = new List<Unit>();
List<Units> otherUnits = new List<Unit>();

// populate units with various Measures and Weights.
// populate otherUnits with various Measures and Weights.
foreach(Unit u in units)
{
 u.Add( 
         // add something from the otherUnits collection. Typesafe, etc.
      ); 
} 

我试过..

public abstract T Add<T>(T unit) where T : Unit;
单元类中的

,但是当我尝试用适当的类填充“T”时,我得到了关于它如何不是继承类中的适当标识符的错误。有什么想法吗?

4 个答案:

答案 0 :(得分:4)

您需要更改Unit抽象类以采用泛型类型:

abstract class Unit<T>

然后你可以添加Add抽象方法:

void Add(T unit);

所以你的测量和重量等级现在看起来像:

class Measure : Unit<Measure>
class Weight : Unit<Weight>

或者,将以下抽象方法添加到Unit

abstract void Add(Unit unit);

然后你需要在继承类中使用类型检查来约束它:

void Add(Unit unit)
{
    if (unit.GetType() != this.GetType())
    {
        throw new ArgumentException("You can only add measurements.");
    }
}

答案 1 :(得分:0)

如果你的层次结构足够稳定,你可以使用访问者模式的想法来提出这样的结论:

abstract class Unit {
  public abstract Unit Add(Unit unit);
  public virtual Measure Add(Measure unit) { return unit; }
  public virtual Weight Add(Weight unit) { return unit; }
}

class Measure : Unit {
  public override Measure Add(Measure unit) { 
    // ...
  }
  public override Unit Add(Unit unit) {
    return unit.Add(this);
  }
}

class Weight : Unit {
  public override Weight Add(Weight unit) {
    // ...
  }
  public override Unit Add(Unit unit) {
    return unit.Add(this);
  }
}

如果您预计稍后会将其他行为添加到层次结构中,您甚至可以使用真正的访问者并将其与Unit类分开。

注意:如果Add将更改当前实例,则if应返回void

答案 2 :(得分:0)

我实际上是从GenericTypeTea那里得到了这个想法,但我尝试使用不同的方法。

public interface IUnit
{
    T Add<T>(T unit) where T : IUnit<T>;
}

public interface IUnit<T>
{
    T Add(T unit);
}

    abstract class Unit : IUnit
    {
    }

    class Measure : Unit, IUnit<Measure>
    {
    public Measure Add(Measure unit)
    {
        throw new NotImplementedException();
    } 
    }

    class Weight : Unit, IUnit<Weight>
    {
    public Weight Add(Weight unit)
    {
        throw new NotImplementedException();
    }
    }

答案 3 :(得分:0)

如果您必须使用两个基类列表:

public abstract class Unit()
{
    public abstract Unit Add(Unit other);

    public void MatchType(Unit other)
    {
        if(this.GetType() != other.GetType()) 
            throw new ArgumentException("Units not of same type");
    }
}

...然后在每个派生类中实现以下内容:

public override void Add(Unit other)
{
   MatchType(other);

   //actual implementation
}

然后使用实际的Add实现在派生类中扩展此功能。

老实说,我没有看到你想要做的事情的重点。除非两个列表仅包含Measures或Only Weights,否则它将无效,并且您只是通过将类型检查放入Unit中而将该事实隐藏起来。那只是在寻找麻烦。

我将按如下方式定义您拥有这两个列表的代码:

public List<T> AddLists<T>(List<T> firstList, List<T> secondList) where T:Unit
{
   //your code to add elements
}

...然后使用通用的Unit.Add()方法,如下所示:

public static void Add<T>(this T item, T other) where T:Unit
{
   //perform something that works like item += other
}

您必须使用强力键入权重或计量的列表。您可以尝试使用Linq转换List的泛型参数:

listOfMeasures = listOfUnits.OfType<Weight>().ToList();

当然,这会导致权重从列表中过滤掉,但这对您有利:

listOfWeights = listOfUnits.OfType<Weight>().ToList();
listOfMeasures = listOfUnits.OfType<Measure>().ToList();

var addedListOfMeasures = AddLists(listOfMeasures, otherListOfMeasures);
var addedListOfWeights = AddLists(listofWeights, otherListOfWeights);

上面的代码与我列出的通用AddLists和Unit.Add()方法一起使用,将是类型安全的,因此不会抛出任何运行时异常。做不好;您创建的任何新单元都需要添加更多代码来处理每种新类型。