Ограничения атрибутов для обобщений C # - PullRequest
5 голосов
/ 28 марта 2012

У меня есть следующее объявление метода:

public static bool SerializeObject<T>(string filename, T objectToSerialize){

Я хочу ограничить T типами, украшенными атрибутом [Serializable].

Следующее не работает, потому что "Атрибут"«System.SerializableAttribute» недопустим для этого типа объявления. Он действителен только для объявлений «Class, Enum, Struct, Delegate». ":

public static bool SerializeObject<T>(string filename, [Serializable] T objectToSerialize)

Я понимаю, что AttributeUsageAttribute(AttributeTargets.Parameter) должно быть установлено дляАтрибут для того, чтобы использовать вышеупомянутое и что атрибут [Serializable] не имеет этого набора.

Есть ли способ ограничить T типами, отмеченными атрибутом [Serializable]?

Ответы [ 5 ]

9 голосов
/ 28 марта 2012

Есть ли способ ограничить T типами, помеченными атрибутом [Serializable]?

Нет, нет способа сделать это, используя общие ограничения. Эти ограничения четко прописаны в спецификации, и это не одно из них.

Однако вы можете написать метод расширения

public static bool IsTypeSerializable(this Type type) {
    Contract.Requires(type != null);
    return type.GetCustomAttributes(typeof(SerializableAttribute), true)
               .Any();
}

и сказать

Contract.Requires(typeof(T).IsTypeSerializable());

Нет, это не одно и то же, но это лучшее, что вы можете сделать. Ограничения на дженерики довольно ограничены.

Наконец, вы можете подумать:

where T : ISerializable

Опять же, не то же самое, но это то, что нужно учитывать.

1 голос
/ 28 марта 2012

Вы можете просто сгенерировать исключение, чтобы программист знал, что он должен быть Serializable.

вроде так:

public static bool SerializeObject<T>(string filename, T objectToSerialize)
{
    if(!typeof(objectToSerialize).IsSerializable)
    {
              throw new Exception("objectToSerialize is not serializable");
    }
}
1 голос
/ 28 марта 2012

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

if (!typeof(T).GetCustomAttributes(typeof(SerializableAttribute), true).Any())
{
    throw new ArgumentException();
}
0 голосов
/ 28 марта 2012

Нет. Атрибуты не являются ограничениями, но представляют собой информацию, добавляемую к метаданным. Вы можете проверить, был ли установлен атрибут с:

If(typeof(T).GetCustomAttributes(typeof(SerializableAttribute), false).Length == 0) {
    throw new ...
}

Логический параметр определяет, следует ли учитывать унаследованные атрибуты.

0 голосов
/ 28 марта 2012

Нет, нет. Однако вы можете ограничить тип реализацией ISerializable, которая отличается от декорации с помощью SerializableAttribute.

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