Ограничение T на строку и int? - PullRequest
17 голосов
/ 18 января 2009

Я создал общий класс коллекции, который определяется следующим образом.

public class StatisticItemHits<T>{...}

Этот класс может использоваться только со значениями int и string. Однако это

public class StatisticItemHits<T> where T : string, int {...}

не скомпилируется. Что я делаю не так?

Ответы [ 7 ]

15 голосов
/ 18 января 2009

Ограничение типа предназначено для использования с интерфейсами. Ваш пример предполагает, что вы хотите разрешить классы, которые наследуют от int и строки , что является своего рода бессмыслицей. Я предлагаю вам разработать интерфейс, содержащий методы, которые вы будете использовать в своем родовом классе StatisticItemHits, и использовать этот интерфейс в качестве ограничения. Однако я не вижу ваших требований здесь, может быть, вы могли бы опубликовать более подробную информацию о вашем сценарии?

6 голосов
/ 18 января 2009

Вы можете сделать StatisticItemHits<T> абстрактный класс и создать два подкласса:

StatisticItemHitsInt : StatisticItemHits<int>{}

StatisticItemHitsString : StatisticItemHits<string>{}

Таким образом, могут быть только int и строковое представление StatisticItemHits

5 голосов
/ 18 января 2009

Как уже говорили другие, вы не можете использовать ограничения типа таким образом. Что вы можете сделать, так это специализироваться на вашем базовом типе следующим образом:

public class StatisticItemHits <T> { }

public class StringStatisticItemHits : StatisticItemHits<string> { }

public class IntegerStatisticItemHits : StatisticItemHits<int> { }

Кроме того, поскольку ваш базовый класс является универсальным, вы не сможете использовать его для полиморфности. Если вам нужно сделать это, заставьте StatisticItemHits реализовать интерфейс и использовать его для ссылки на экземпляры. Что-то вроде:

public class StatisticItemHits <T> : IStaticticItemHits { }

public interface IStatisticItemHits { }
2 голосов
/ 18 января 2009

Учитывая, что у вас есть только два типа здесь, я бы вместо этого пошел по маршруту OO и просто имел бы два класса для этих двух типов.

Дженерики лучше всего использовать там, где обстоятельства, при которых они могут быть применены, как вы знаете, дженерики . Они намного менее полезны в подобных обстоятельствах.

Вы можете ограничиться только структурами или типами классов, и я думаю, что должны быть числовые или операторные ограничения (например, должны поддерживать + =)

Int и string действительно сильно отличаются друг от друга, и, конечно, они отличаются от int и double. Для универсального класса не имеет смысла поддерживать неизменяемый ссылочный тип строки и тип значения int, не поддерживая также другие типы, более похожие на любой из них.

1 голос
/ 18 января 2009

Вы не можете ограничить его до string и int из условия where. Вы можете проверить это в конструкторе, но это, вероятно, не очень хорошее место для проверки. Мой подход заключается в том, чтобы специализировать класс и абстрагировать создание класса в (полу) фабричный шаблон:

class MyRestrictedGeneric<T>
{
    protected MyRestrictedGeneric() { }


    // Create the right class depending on type T
    public static MyRestrictedGeneric<T> Create<T>()
    {
        if (typeof(T) == typeof(string))
            return new StringImpl() as MyRestrictedGeneric<T>;

        if (typeof(T) == typeof(int))
            return new IntImpl() as MyRestrictedGeneric<T>;

        throw new InvalidOperationException("Type not supported");
    }


    // The specialized implementation are protected away
    protected class StringImpl : MyRestrictedGeneric<string> { }
    protected class IntImpl : MyRestrictedGeneric<int> { }
}

Таким образом, вы можете ограничить использование класса только строкой и int внутри внутри вашего класса.

1 голос
/ 18 января 2009

Невозможно сделать это с помощью «где». Вы не можете сделать «или».

0 голосов
/ 14 января 2014

Просто используйте:

where TSource : IEquatable<string>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...