2010-11-10 20 views
12

donné un exemple, comme ..l'aide des attributs pour les contraintes génériques

public interface IInterface { } 

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

Cela fonctionne très bien, mais je me demandais s'il est possible d'utiliser un attribut comme une contrainte. Tels que ...

class InsertableAttribute : Attribute 

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

De toute évidence, cette syntaxe ne fonctionne pas, ou je ne serais pas poster la question. Mais je suis juste curieux de savoir si c'est possible ou pas, et comment le faire.

+2

Je voudrais * AMOUR * si cela a été mis en œuvre ... – tenfour

Répondre

11

n ° Vous ne pouvez utiliser que des classes (de base) et des interfaces en tant que contraintes.

Vous pouvez cependant faire quelque chose comme ceci:

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. 
} 
+0

Merci. C'est ce que je pensais, mais je pensais que ça valait le coup d'essayer. Mon projet n'en a pas besoin, mais j'ai pensé que c'était une bonne information à connaître. Je clique sur la case à cocher «Accepter» dans 5 minutes lorsque Stack Overflow me le permet. – Ciel

+0

De rien. –

+0

Si vous avez besoin de l'attribut pour un traitement externe, pour lequel une interface que vous contrôlez est le marqueur, vous pouvez déclarer l'attribut sur l'interface et sélectionner les attributs hérités. – smartcaveman

7

Non Vous ne pouvez utiliser des classes, interfaces, class, struct, new(), et d'autres paramètres de type comme des contraintes.

Si InsertableAttribute spécifie [System.AttributeUsage(Inherited=true)], vous pouvez créer une classe fictive comme:

[InsertableAttribute] 
public class HasInsertableAttribute {} 

et limiter votre méthode comme:

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

Alors T aurait toujours l'attribut même si elle était seulement venant de la classe de base. Les classes d'implémentation pourraient "surcharger" cet attribut en le spécifiant sur elles-mêmes.

+0

Et d'autres paramètres de type :) –

+0

@Jon Skeet Ah, bien sûr. Je savais que j'oubliais quelque chose, merci de le signaler! –

-1

Non, vous ne pouvez pas. Votre question ne concerne pas les attributs, mais la conception orientée objet. S'il vous plaît lire ce qui suit pour en savoir plus sur generic type constraint.

Je suggère plutôt effectuer les opérations suivantes:

public interface IInsertable { 
    void Insert(); 
} 

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

Alors que l'idée est d'avoir une interface IInsertable et implémente cette interface dans une classe chaque fois que vous voulez être insérable. De cette façon, vous restreindrez automatiquement l'insertion pour les éléments insérables.

Il s'agit d'une approche plus flexible, qui vous permettra de conserver des informations identiques ou différentes d'une entité à une autre, car vous devez implémenter l'interface vous-même dans votre classe.

+0

Eh bien, je n'ai pas besoin de le faire du tout. C'est plutôt une de ces choses où vous codifiez quelque chose, et cela vous frappe comme une idée qui pourrait être utile pour autre chose.En vérité, si j'avais besoin d'assurer une contrainte à un attribut, j'utiliserais simplement une classe factice. – Ciel

+0

Je comprends ce que vous voulez dire, et il y a des moments où vous pensez à quelque chose et vous vous demandez si c'est faisable. =) Question intéressante de toute façon. =) –