c# - 如何解决泛型类 <T> 场景?

标签 c# class mvvm interface

我在使用泛型时遇到了问题。我正在创建一个名为 IProblem 的接口(interface),其中每个问题都有结果(答案)和结果(如果正确)

public interface IProblem<T>
{
    ushort ResultCount { get; }
    T[] Results { get; }

    bool IsCorrect();
}

public abstract class ProblemBase<T> : IProblem<T>
{
    private T[] _results;
    private ushort? _resultCount;

    public ushort ResultCount
    {
        get
        {
            if (_resultCount == null) throw new ArgumentNullException("_resultCount");
            return (ushort)_resultCount;
        }
        protected set
        {
            if (_resultCount != value)
                _resultCount = value;
        }
    }

    public T[] Results
    {
        get
        {
            if (_results == null)
                _results = new T[ResultCount];

            return _results;
        }
    }

    public abstract bool IsCorrect();
}

这是我创建算术问题的示例,称为 ProblemA . Tdecimal因为数组数据类型应该是十进制(其他问题可能有 stringint )
public class ProblemA: ProblemBase<decimal>
{
    private decimal _number1;
    private decimal _number2;
    private Operators _operator;

    public decimal Number1
    {
        get { return _number1; }
        set { _number1 = value; }
    }

    public decimal Number2
    {
        get { return _number2; }
        set { _number2 = value; }
    }

    public Operators Operator
    {
        get { return _operator; }
        set { _operator = value; }
    }

    public decimal Result
    {
        get { return Results[0]; }
        set { Results[0] = value; }
    }

    public ProblemA()
    {
        this.ResultCount = 1;
    }

    public override bool IsCorrect()
    {
        bool result;

        switch (_operator)
        {
            case Operators.Addition:
                result = this.Result == (this.Number1 + this.Number2);
                break;
            case Operators.Subtract:
                result = this.Result == (this.Number1 - this.Number2);
                break;
            case Operators.Multiplication:
                result = this.Result == (this.Number1 * this.Number2);
                break;
            case Operators.Division:
                result = this.Result == (this.Number1 / this.Number2);
                break;
            default:
                throw new ArgumentException("_operator");
        }

        return result;
    }
}

我正在使用 MVVM,所以我想为每个包含 ProblemBase<T> 的问题提供一个 ViewModel作为属性,但它是如何通用的,我想如果放入 IProblemViewModel 将是一个问题作为通用的。
public interface IProblemViewModel : IViewModel
{
    ProblemBase<T> Problem { get; set; }
}

我这么说是因为后来计划使用 ObservableCollection<IProblemViewModel> , 所以我不确定如果我写 IProblemViewModel 是否没有问题或 IProblemViewModel<T> .
提前致谢。

最佳答案

也许我还没有完全理解这一点,但这就是你所追求的吗?

    ObservableCollection<IProblemViewModel<object>> collection = new ObservableCollection<IProblemViewModel<object>>
    {
        new ProblemViewModel<DerivedResult>(),
        new ProblemViewModel<OtherResult>()
    };

这可以通过将泛型参数声明为协变来实现。

您还可以将集合更改为
ObservableCollection<IProblem<BaseType>>

并让它接受特定的结果链。在此示例中,DerivedResult 和 OtherResult 必须从 BaseType 继承以适合集合。

最大的警告是原始类型不适合这种层次结构,无论如何。您必须将它们包装在 IProblem<IntResult> 中等等。

当然,您可以实现一个简单的载体,例如 Boxer,它将装箱任何值类型,而不是为每种类型实现一个。

最后一个警告:协变类型不可能有一个“set”属性,所以 IProblemViewModel只能支持get .

一个完整的、可编译的例子:
class Program
{

    public interface IProblem<out T>
    {
        ushort ResultCount { get; }
        T[] Results { get; }

        bool IsCorrect();
    }

    public class ProblemBase<T> : IProblem<T>
    {
        private T[] _results;
        private ushort? _resultCount;

        public ushort ResultCount
        {
            get
            {
                if (_resultCount == null) throw new ArgumentNullException("_resultCount");
                return (ushort)_resultCount;
            }
            protected set
            {
                if (_resultCount != value)
                    _resultCount = value;
            }
        }

        public T[] Results
        {
            get
            {
                if (_results == null)
                    _results = new T[ResultCount];

                return _results;
            }
        }

        public bool IsCorrect()
        {
            return true;
        }
    }

    public interface IProblemViewModel<out T>
    {
        IProblem<T> Problem { get; }
    }

    public class BaseResult
    {

    }

    public class DerivedResult : BaseResult
    {

    }

    public class OtherResult : BaseResult
    {

    }

    public class ProblemViewModel<T> : IProblemViewModel<T>
    {

        public IProblem<T> Problem
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    }


    static void Main(string[] args)
    {
        ObservableCollection<IProblemViewModel<object>> collection = new ObservableCollection<IProblemViewModel<object>>
        {
            new ProblemViewModel<DerivedResult>(),
            new ProblemViewModel<OtherResult>()
            //, new ProblemViewModel<int>()   // This is not possible, does not compile.
        };
    }
}

关于c# - 如何解决泛型类 <T> 场景?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8843832/

相关文章:

c# - 我应该提交 visual studio 项目的哪一部分?

c# - Unity - InjectionProperty 导致空属性?

c# - 如何创建一个 IObservable<T> 每 -n- 秒返回一个值而不跳过任何

python - 如何设置字典值使其表现得像实例属性?

silverlight - ItemTemplate 中 DataContext 的访问属性

c# - 具有不同参数名称的多个参数的 MVC 路由

Python:新类、继承和重写

c# - 如何创建一个没有任何构造函数的类,就像 MessageBox 类一样

WPF 图像源与 StringFormat 绑定(bind)

c# - 模型中的 INotifyPropertyChanged