简体   繁体   中英

c# where for generic type constraint class may NOT be

I would like to exclude some types for being used in a generic class. I know how to make constrains in order to make sure a generic type is some kind of (interface) type. But I can't seem to figure out how to exclude (multiple) types.

For instance: I want a generic class to exclude ints and uints (but don't exclude DateTime for instance, so not all Primitives may be excluded).

I can't do something like this:

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

Can someone help me out how to exclude multiple types at once?


I made a special class that acts like a dictionary and is also a FiFo collection with an index, where 0 is the most recent value, 1 the previous etc. ( public class FiFoDictionary<K, V>: IDictionary<K, V> , which uses OrderedDictionary as the internal dict.)

But since the index is given via an int , this gives issues when the key of the dictionary is an int . Because then you get the value linked to the key, instead of the index. Or is there any way to force the use of the index instead of the key for an OrderedDictionary ?

Given the explanation in the comment, why you think you need this: No, you don't need to exclude int from the generic type.

When overloaded methods in a class (methods that differ by type of their parameters only) are used in a generic class, then the decision which of the methods is called is already made while the Generic class is compiled independently of the concrete type then used later on.

Example:

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);
}

The output is

"Triggered object"

Even when T is int , the overloaded Internal method that takes an int is never called because the decision that Trigger calls the Internal method that expects an object is already made for the whole generic class independently of the concrete type used.


The same is true when you use an OrderedDictionary internally. myOrderedDictionary[x] where x is a generic type will always use the index property that accesses entries by key and not the one that accesses them by order because this decision is made based on the known constraints of the generic type independently of the concrete type used later on.

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"
}

There is no such thing in C# however you can scope the generic type in a way that may help you to achieve that. This is just a sample and I don't consider this as a solution to your problem

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 () { }

its no posible to do, The.= and == operators can't be used because there's no guarantee that the concrete type argument will support these operators. here you can read more about

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM