Использование атрибутов для общих ограничений

Приведенный пример, такой как..

public interface IInterface { }

public static void Insert<T>(this IList<T> list, IList<T> items) where T : IInterface
{
 // ... logic
}

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

class InsertableAttribute : Attribute

public static void Insert<T>(this IList<T> list, IList<T> items) where T : [Insertable]
{
 // ... logic
}

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

3 ответа

Решение

Нет. Вы можете использовать только (базовые) классы и интерфейсы в качестве ограничений.

Однако вы можете сделать что-то вроде этого:

public static void Insert<T>(this IList<T> list, IList<T> items)
{
    var attributes = typeof(T).GetCustomAttributes(typeof(InsertableAttribute), true);

    if (attributes.Length == 0)
        throw new ArgumentException("T does not have attribute InsertableAttribute");

    /// Logic.
}

Нет. Вы можете использовать только классы, интерфейсы, class, struct, new()и другие параметры типа в качестве ограничений.

Если InsertableAttribute указывает [System.AttributeUsage(Inherited=true)]тогда вы можете создать фиктивный класс, например:

[InsertableAttribute]
public class HasInsertableAttribute {}

а затем ограничить ваш метод, как:

public static void Insert<T>(this IList<T> list, IList<T> items) where T : HasInsertableAttribute
{
}

затем T всегда будет иметь атрибут, даже если он только идет из базового класса. Реализующие классы смогут "переопределить" этот атрибут, указав его для себя.

Нет, ты не можешь. Ваш вопрос не об атрибутах, а об объектно-ориентированном дизайне. Пожалуйста, прочитайте следующее, чтобы узнать больше о generic type constraint,

Я скорее предлагаю вам сделать следующее:

public interface IInsertable {
    void Insert();
}

public class Customer : IInsertable {
    public void Insert() {
        // TODO: Place your code for insertion here...
    }
}

Так что идея состоит в том, чтобы иметь IInsertable интерфейс и реализует этот интерфейс внутри класса, когда вы хотите быть вставляемым. Таким образом, вы автоматически ограничите вставку для вставляемых элементов.

Это более гибкий подход, и он позволит вам легко сохранять ту же самую или иную информацию от объекта к другому, так как вы должны сами реализовать интерфейс в своем классе.

Другие вопросы по тегам