c# where for generic type constraint class 可能不是

c# where for generic type constraint class may NOT be

我想排除某些类型以用于泛型 class。我知道如何进行约束以确保泛型类型是某种(接口)类型。但我似乎无法弄清楚如何排除(多种)类型。

例如:我想要一个泛型 class 来排除整数和单位(但不排除 DateTime,例如,因此可能不会排除所有基元)。

我不能做这样的事情:

public class SomeWhereTest2<T> where T : !System.Int32 
{ 
}

谁能帮我看看如何一次排除多种类型?


我制作了一个特殊的class,它的作用类似于字典,也是一个带有索引的 FiFo 集合,其中 0 是最近的值,1 是前一个值,依此类推。(public class FiFoDictionary<K, V>: IDictionary<K, V>,其中使用 OrderedDictionary 作为内部字典。)

但是由于索引是通过 int 给出的,因此当字典的键是 int 时会出现问题。因为那样你会得到链接到键的值,而不是索引。或者有什么方法可以强制使用索引而不是 OrderedDictionary 的键?

不可能,不能使用 != 和 == 运算符,因为不能保证具体类型参数将支持这些运算符。 here you can read more about

C# 中没有这样的东西,但是您可以通过某种方式确定泛型类型的范围,从而帮助您实现这一点。这只是一个示例,我不认为它可以解决您的问题

class MyGeneric<T> where T : new() { } // T must be a class with default constructor
class MyGeneric<T> where T : System.IComparable<T> { }// T must implement IComparable interface 
class MyGeneric<T> where T : System.IComparable<T>, new () { }

鉴于评论中的解释,你认为你需要这个的原因:不, 您不需要从通用类型中排除 int

当 class 中的重载方法(仅参数类型不同的方法)在泛型 class 中使用时,已经决定调用哪个方法,同时Generic class 是独立于具体类型编译的,然后在后面使用。

示例:

class Test<T>
{
    public void Trigger(T test)
    {
        // Will always call Internal(object) and never call Internal(int) even when T is int.
        Internal(test);
    }

    private void Internal(int test)
    {
        MessageBox.Show("Triggered int");
    }

    private void Internal(object test)
    {
        MessageBox.Show("Triggered object");
    }
}

private void buttonTest_Click(object sender, EventArgs e)
{
    Test<int> test = new Test<int>();
    test.Trigger(42);
}

输出为

"Triggered object"

即使 Tint,采用 int 的重载 Internal 方法也永远不会被调用,因为 Trigger 调用 Internal 期望 object 的方法已经为整个通用 class 独立于所使用的具体类型。


在内部使用 OrderedDictionary 时也是如此。 myOrderedDictionary[x] 其中 x 是泛型类型,将始终使用索引 属性 来按键访问条目,而不是按顺序访问条目的索引,因为此决定是基于已知的约束做出的独立于稍后使用的具体类型的通用类型。

class TestDictionary<TKey, TValue> 
{
    OrderedDictionary orderedDictionary = new OrderedDictionary();

    public void Add(TKey key, TValue value)
    {
        orderedDictionary.Add(key, value);
    }

    public TValue GetByIndex(int index)
    {
        return (TValue)orderedDictionary[index];
    }

    public TValue GetByKey(TKey key)
    {
        return (TValue)orderedDictionary[key];
    }
}

private void buttonTest_Click(object sender, EventArgs e)
{
    TestDictionary<int, string> test = new TestDictionary<int, string>();

    test.Add(42, "Test");

    MessageBox.Show(test.GetByIndex(0)); // Correct output "Test"
    MessageBox.Show(test.GetByKey(42)); // Correct output "Test"
}