泛型类和简化约束?

时间:2017-07-10 08:05:17

标签: c# generics

让我们说我有一个通用接口IFace<T, U>TU可以通过其他方式加以约束,但我不认为这与问题相关。

我想创建一个新的泛型类GenClass,其定义如下:

class GenClass<T> where T: IFace

即。我想告诉编译器GenClass应该处理IFace的任何实现而不指定泛型类型。

这可能,还是我需要指定TU通用参数?

我已经尝试过编写IFace以及IFace<>IFace<,>,但是编译器总是很合适 - 所以我认为这是无法做到的。不过,也许我会以错误的方式解决这个问题?

3 个答案:

答案 0 :(得分:7)

  

这是可能的,还是我需要指定T和U通用参数?

你需要它们,我很害怕。你需要

class GenClass<T, TX, TY> where T : IFace<TX, TY>

假设您无法创建通用的非通用IFace接口 - 这通常是最简单的方法:

public interface IFace
{
    // Include anything that doesn't need the type parameters here
}

public interface IFace<T1, T2> : IFace
{
    // Include anything that needs the type parameters here
}

然后你可以:

class GenClass<T> where T : IFace

因为现在非通用接口确实存在。

答案 1 :(得分:1)

不,你不能那样做。最接近的是:

interface IFace { }
interface IFace<T, U>: IFace { }
class GenClass<T> where T: IFace

否则你坚持:

class GenClass<T, TFace, UFace> where T: IFace<TFace, UFace>

根据您的问题,您似乎对TFace中的UFaceGenClass不感兴趣,因此非通用界面应该这样做。

答案 2 :(得分:0)

您可以执行以下操作。

class GenClass<T, TT, TU> where T: IFace<TT, TU>

然后在初始化GenClass时,您可以定义所有三个参数。

class MyFace<T, U> : IFace<T, U>

var instance = new GenClass<MyFace<string, int>>();

或者

class MyFace : IFace<string, int>

var instance = new GenClass<MyFace>();

如果你想提供一个非通用的基本类型,它可以知道例如两个属性,你也可以这样做。

interface IFace<T, U>
{
    T ValueOne { get; set; }
    U ValueTwo { get; set; }
}

abstract class FaceBase : IFace<object, object>
{
    public object ValueOne { get; set; }
    public object ValueTwo { get; set; }

    protected FaceBase(object valueOne, object valueTwo)
    {
        ValueOne = valueOne;
        ValueTwo = valueTwo;
    }
}

class GenClass<T> where T : FaceBase
{
    private T Value { get; set; }

    public GenClass()
    {
        // do something with Value.ValueOne or Value.ValueTwo
    }
}

FaceBase的实现如下所示。

class MyFace : FaceBase, IFace<string, int>
{
    public new string ValueOne
    {
        get => base.ValueOne as string;
        set => base.ValueOne = value;
    }

    public new int ValueTwo
    {
        get => (int) base.ValueTwo;
        set => base.ValueTwo = value;
    }

    public MyFace(string valueOne, int valueTwo)
        : base(valueOne, valueTwo)
    { }
}