简化c#中的循环泛型约束

本文关键字:泛型 约束 循环 简化 | 更新日期: 2023-09-27 18:19:19

给定以下基类:

public abstract class PurchaseSystemControllerBase<TController, TViewModel> : IInitializable
    where TController : PurchaseSystemControllerBase<TController, TViewModel>
    where TViewModel : PurchaseSystemViewModelBase<TController, TViewModel> {
    protected TViewModel ViewModel { get; private set; }
    ...
}
public abstract class PurchaseSystemViewModelBase<TController, TViewModel> : ViewModelBase
    where TController : PurchaseSystemControllerBase<TController, TViewModel>
    where TViewModel : PurchaseSystemViewModelBase<TController, TViewModel> {
    protected TController Controller { get; private set; }
    ...
}

具体实现如下:

public sealed class PurchaseSystemController : PurchaseSystemControllerBase<PurchaseSystemController, PurchaseSystemViewModel> {
    ...
}
public sealed class PurchaseSystemViewModel : PurchaseSystemViewModelBase<PurchaseSystemController, PurchaseSystemViewModel> {
    ...
}

是否有一种方法可以简化它,使以下内容成为可能?

public sealed class PurchaseSystemController : PurchaseSystemControllerBase<PurchaseSystemViewModel> {
    ...
}
public sealed class PurchaseSystemViewModel : PurchaseSystemViewModelBase<PurchaseSystemController> {
    ...
}

简化c#中的循环泛型约束

不,不幸的是没有-至少,我不知道,在不失去一些类型安全的情况下。在我的Protocol Buffers端口中,在消息类型和相应的构建器类型之间,我有一个非常相似的设置。

如果你很乐意用一些非泛型的基本类型声明ViewModelController属性,那么这很好-但是如果你需要这两个属性确切地知道相应的类型,你就会留下这种混乱。

(注意,您可能需要考虑ViewModel和Controller 是否应该都知道彼此)

不,在保持完全强类型的情况下,这是不可能的。下面是一个示例,说明如何将其简化为更基本的类型:

public abstract class PurchaseSystemControllerBase : IInitializable {
    protected PurchaseSystemViewModelBase ViewModel { get; private set; }
}
public abstract class PurchaseSystemControllerBase<TViewModel>
                    : PurchaseSystemControllerBase
    where TViewModel : PurchaseSystemViewModelBase {
    // note: property implementations should prevent this and base.ViewModel
    // from getting out of sync
    protected new TViewModel ViewModel { get; private set; }
}
public abstract class PurchaseSystemViewModelBase : ViewModelBase {
    protected PurchaseSystemControllerBase Controller { get; private set; }
}
public abstract class PurchaseSystemViewModelBase<TController>
                    : PurchaseSystemViewModelBase
    where TController : PurchaseSystemControllerBase {
    // note: property implementations should prevent this and base.Controller
    // from getting out of sync
    protected new TController Controller { get; private set; }
}

public sealed class PurchaseSystemController
                  : PurchaseSystemControllerBase<PurchaseSystemViewModel> {
}
public sealed class PurchaseSystemViewModel
                  : PurchaseSystemViewModelBase<PurchaseSystemController> {
}

这可能是足够的,特别是考虑到这些是protected属性。