【问题标题】:Generic class to create concrete class automatically通用类自动创建具体类
【发布时间】:2011-10-21 15:58:32
【问题描述】:

有没有办法取接口,说:

/// <summary>
/// Interface containing operators which operate on T
/// </summary>
public interface IScalarOperators<T>
{
    // Adds two T objects
    IOperateScalar<T> OperatorAdd { get; }
    // Subtracts two T objects
    IOperateScalar<T> OperatorSubtract { get; }
    // Multiplies two T objects
    IOperateScalar<T> OperatorMultiply { get; }
}

// Class containing all the Scalar operators for a given T
class ScalarOperators<T> : IScalarOperators<T>
{
    public IOperateScalar<T> OperatorAdd { get; private set; }
    public IOperateScalar<T> OperatorSubtract { get; private set; }
    public IOperateScalar<T> OperatorMultiply { get; private set; }
    private ScalarOperators(IOperateScalar<T> add, IOperateScalar<T> subtract, IOperateScalar<T> multiply)
    {
        this.OperatorAdd = add;
        this.OperatorSubtract = subtract;
        this.OperatorMultiply = multiply;
    }

    public static ScalarOperators<bool> CreateBool()
    {
        return new ScalarOperators<bool>(new AddBool(), new SubtractBool(), new MultiplyBool());
    }

    public static ScalarOperators<int> CreateInt()
    {
        return new ScalarOperators<int>(new AddInt(), new SubtractInt(), new MultiplyInt());
    }

    // METHOD I WANT TO ADD
    public static ScalarOperators<T> Create()
    {
      // if T == bool
      // return CreateBool()
      // if T == int
      // return CreateInt()
      // else (no definition available for T)
      // return null
    }

    // I tried something like below, but it didn't work...
    public static ScalarOperators<T> Create<T>() where T: bool
    { return CreateBool(); }

    public static ScalarOperators<T> Create<T>() where T : int
    { return CreateInt(); }

    public static ScalarOperators<T> Create<T>()
    { return null; }
}

注意,我想要一个通用的 Create 方法来创建正确的运算符集,但我不知道该怎么做。

我想用它从这个方法中删除参数:

    public static IMatrix<T> Add<T>(this IMatrix<T> matrix, IMatrix<T> other, IScalarOperators<T> operators)
    {
        JoinCells<T> joiner = new JoinCells<T>();
        return joiner.Join(matrix, other, null, operators.OperatorAdd);
    }

变成

    public static IMatrix<T> Add<T>(this IMatrix<T> matrix, IMatrix<T> other)
    {
        JoinCells<T> joiner = new JoinCells<T>();
        return joiner.Join(matrix, other, null, ScalarOperators<T>.Create().OperatorAdd);
    }

感谢您的帮助!主要是,我只是不想将 scalarOperator 对象传递给扩展方法,我更喜欢使用“默认值”,因为 ScalarOperators 不太可能针对定义的任何 T 进行更改。

【问题讨论】:

  • 看起来您正在尝试创建一个库以允许通用计算?您可能对this library 感兴趣。最近,表达式树提供了一种不同的解决方案,看起来也很不错。查看Marc Gravell's MiscUtils 实现。

标签: c# .net generics default-implementation


【解决方案1】:

我建议创建一个 IScalarOperators 工厂而不是静态类(如果你真的需要它是静态的,你可以通过静态字段访问它)。 您可以在应用启动时注册它们并通过此示例方法获取它们:

 public IScalarOperators<T> Create<T>()
 {
    // check if exists in dictionary
    return (ScalarOperators<T>)dict[typeof(T)];
 }

dict 将是 Dictionary 类型。 好处是您可以在应用程序增长期间添加新的 IScalarOperators,只需创建新的实现类并在工厂中注册它,强制转换是一个缺点。此外,您将更好地分离关注点和(在我看来)更简洁的代码。

【讨论】:

    【解决方案2】:

    你需要做的是获取T的类型。

    您的 Create 方法可能是这样的:

    public static ScalarOperators<T> Create()
    {
        Type type = typeof(T); 
        if(type == typeof(bool))
          return CreateBool()
        if(type == typeof(int))
          return CreateInt()
        else
          return null
    }
    

    【讨论】:

      【解决方案3】:

      这里发生了一些我认为应该解决的事情。您试图将自定义运算符与它们所操作的类型分开,这会造成混淆,并且您试图采用泛型的非常广泛的概念,然后对它们进行专门化。

      对于第一个,您总是要对同一类型使用相同的运算符(至少,您永远不会尝试在 int 类型上使用布尔运算符)。没有理由通过为它们设置一个单独的类来使事情复杂化。对于后者,泛型类和泛型方法对于任何给定的 T 都是一样的。当然,您很可能在静态工厂方法中获得 typeof(T) 并与几个特定情况进行比较,然后您将由于这种过于复杂的通用操作数结构,必须为您要处理的每个新 T 更改它。

      我建议为您的操作数创建一个通用接口,然后为这些类型实现一个包装器。例如 int 可以这样包装。

      public interface IScalarOperators<T>
      {
          IScalarOperators<T> Add (IScalarOperators<T> rightSide);
          IScalarOperators<T> Subtract (IScalarOperators<T> rightSide);
          IScalarOperators<T> Multiply (IScalarOperators<T> rightSide);
          T Unwrap();
      }
      
      public interface IMatrix<T> where T : IScalarOperators<T> { /* whatever */ }
      
      public class CustomInt : IScalarOperators<CustomInt>
      {
          private readonly int number;
          public CustomInt(int number) { this.number = number; }
          public CustomInt Unwrap() { return this; }
          public IScalarOperators<CustomInt> Add(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number + rightSide.Unwrap().number); }
          public IScalarOperators<CustomInt> Subtract(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number - rightSide.Unwrap().number); }
          public IScalarOperators<CustomInt> Multiply(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number * rightSide.Unwrap().number); }
      }
      

      此时,您可以通过IScalarOperators&lt;T&gt; 接口对IMatrix&lt;CustomInt&gt; 进行操作,并执行您想要的任何公开操作。作为一个粗略的例子,假设您有一个名为array 的公开访问器,您可以说IScalarOperators&lt;T&gt; result = matrix.array[0, 0].Add(matrix.array[0, 1]); 并获得将两者相加的表示。然后,您可以对其执行任何进一步的操作,依此类推。

      【讨论】:

        猜你喜欢
        • 2014-05-10
        • 1970-01-01
        • 2019-01-05
        • 1970-01-01
        • 2014-11-05
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多