自动创建具体类的泛型类

本文关键字:泛型类 创建 | 更新日期: 2023-09-27 18:12:04

有没有办法取一个接口,比如:

/// <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对象传递给扩展方法,我更喜欢有一个"默认",因为scalarOperator不太可能为定义的任何T更改。

自动创建具体类的泛型类

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

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

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

你需要做的是得到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
}

这里发生了一些事情,我认为应该加以解决。您试图将自定义操作符与它们操作的类型隔离开来,这是令人困惑的,并且您试图采用泛型的非常广泛的概念,然后对它们进行专门化。

对于第一个,您总是要对相同的类型使用相同的操作符(至少,您永远不会尝试在int类型上使用bool操作符)。没有理由通过为它们单独设置一个类来使事情复杂化。对于后者,泛型类和泛型方法对于任何给定的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<T>接口对IMatrix<CustomInt>进行操作,并执行任何您想要的暴露操作。作为一个粗略的示例,假设您有一个名为array的公开访问器,您可以说IScalarOperators<T> result = matrix.array[0, 0].Add(matrix.array[0, 1]);,并获得将两者相加的表示形式。然后可以对其执行任何进一步的操作,等等。