C# 在使用泛型继承类时实现加法

C# 在使用泛型继承类时实现加法,c#,generics,inheritance,language-features,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; } 我基本上想添加一个“add”方法,用于将两个度量值相加,或者将两个权重相加。但它需要在单元基类中。所以基本上如果我有 List<Units> units = new

与结构有关

abstract class Unit
{
 int Id;
}

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

class Weight : Unit
{
 int Minimum;
 int Maximum;
 int Current;
}
我基本上想添加一个“add”方法,用于将两个度量值相加,或者将两个权重相加。但它需要在单元基类中。所以基本上如果我有

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.
      ); 
} 
List units=new List();
列出其他单位=新列表();
//使用各种度量和权重填充单位。
//使用各种度量和权重填充其他单位。
foreach(单位为u,单位为单位)
{
u、 加(
//从otherUnits集合中添加一些内容。
); 
} 
我试过了

public abstract T Add<T>(T unit) where T : Unit;
公共摘要T添加(T单位),其中T:单位;

在Unit类中,但当我尝试用适当的类填充“t”时,我会发现错误,说明它在继承的类中不是适当的标识符。有什么想法吗?

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

abstract class Unit<T>
因此,您的测量和重量等级现在将如下所示:

class Measure : Unit<Measure>
class Weight : Unit<Weight>
然后,您需要在继承类中使用类型检查来约束它:

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

您需要将
单元
抽象类更改为泛型类型:

abstract class Unit<T>
因此,您的测量和重量等级现在将如下所示:

class Measure : Unit<Measure>
class Weight : Unit<Weight>
然后,您需要在继承类中使用类型检查来约束它:

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

如果您的层次结构足够稳定,那么您可以使用访问者模式的思想来提出如下内容:

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);
  }
}
您甚至可以使用一个真正的访问者,并将其与
单元
类分离,如果您预期以后会将其他行为添加到层次结构中


注意:如果
Add
将更改当前实例,那么如果应该返回
void

,如果您的层次结构足够稳定,您可以使用访问者模式的思想来提出如下内容:

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);
  }
}
您甚至可以使用一个真正的访问者,并将其与
单元
类分离,如果您预期以后会将其他行为添加到层次结构中


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

我实际上是从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();
    }
    }
公共接口单元
{
T加(T单位),其中T:IUnit;
}
公共接口单元
{
T加(T单位);
}
抽象类单位:IUnit
{
}
类别度量:单位,单位
{
公共度量添加(度量单位)
{
抛出新的NotImplementedException();
} 
}
类别重量:单位,IUnit
{
公共重量增加(重量单位)
{
抛出新的NotImplementedException();
}
}

我实际上是从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();
    }
    }
公共接口单元
{
T加(T单位),其中T:IUnit;
}
公共接口单元
{
T加(T单位);
}
抽象类单位:IUnit
{
}
类别度量:单位,单位
{
公共度量添加(度量单位)
{
抛出新的NotImplementedException();
} 
}
类别重量:单位,IUnit
{
公共重量增加(重量单位)
{
抛出新的NotImplementedException();
}
}

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

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实现在派生类中扩展此功能

老实说,我不明白你想做什么。除非两个列表都只包含度量值或权重,否则它不会起作用,而您只是通过将类型检查放入单元中来向消费者隐藏这一事实。那只是自找麻烦

我将对这两个列表中的代码进行如下定义:

public List<T> AddLists<T>(List<T> firstList, List<T> secondList) where T:Unit
{
   //your code to add elements
}
public static void Add<T>(this T item, T other) where T:Unit
{
   //perform something that works like item += other
}
public List addlist(List firstList,List secondList),其中T:Unit
{
//您的代码可以添加元素
}
。。。然后使用通用的Unit.Add()方法,如下所示:

public List<T> AddLists<T>(List<T> firstList, List<T> secondList) where T:Unit
{
   //your code to add elements
}
public static void Add<T>(this T item, T other) where T:Unit
{
   //perform something that works like item += other
}
publicstaticvoidadd(此T项,T其他),其中T:Unit
{
//执行类似item+=other的操作
}
您必须使用强类型的列表来称重或测量。您可以尝试使用Linq转换列表的通用参数:

listOfMeasures = listOfUnits.OfType<Weight>().ToList();
listOfMeasures=listOfUnits.OfType().ToList();
当然,这会导致权重从列表中筛选出来,但这会对您有利:

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

var addedListOfMeasures = AddLists(listOfMeasures, otherListOfMeasures);
var addedListOfWeights = AddLists(listofWeights, otherListOfWeights);
listOfWeights=listOfUnits.OfType().ToList();
listOfMeasures=listOfUnits.OfType().ToList();
var addedListOfMeasures=AddList(测量列表、其他测量列表);
var addedListOfWeights=addList(listofWeights,其他listofWeights);

上面的代码与我列出的泛型addList和Unit.Add()方法一起使用,是类型安全的,因此不会引发任何运行时异常。这并不意味着它是好的;您创建的任何新单元都需要向该单元添加更多代码来处理每种新类型。

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

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实现在派生类中扩展此功能

老实说,我不明白你想做什么。除非两个列表都只包含度量值或权重,否则它不会起作用,而您只是通过将类型检查放入单元中来向消费者隐藏这一事实。那只是自找麻烦

我将对这两个列表中的代码进行如下定义:

public List<T> AddLists<T>(List<T> firstList, List<T> secondList) where T:Unit
{
   //your code to add elements
}
public static void Add<T>(this T item, T other) where T:Unit
{
   //perform something that works like item += other
}
public List addlist(List firstList,List secondList),其中T:Unit
{
//您的代码可以添加元素
}
。。。然后使用通用的Unit.Add()方法,如下所示:

public List<T> AddLists<T>(List<T> firstList, List<T> secondList) where T:Unit
{
   //your code to add elements
}
public static void Add<T>(this T item, T other) where T:Unit
{
   //perform something that works like item += other
}
publicstaticvoidadd(此T项,T其他),其中T:Unit
{
//执行类似item+=other的操作
}
您必须使用强类型的列表来称重或测量。您可以尝试使用Linq转换列表的通用参数:

listOfMeasures = listOfUnits.OfType<Weight>().ToList();
listOfMeasures=listOfUnits.OfType().ToList();
当然,这将导致权重从列表中筛选出来,但是