2010-11-10 12 views
12

dato l'esempio, come ..utilizzando attributi per i vincoli generici

public interface IInterface { } 

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

Questo funziona bene, ma mi chiedevo se è possibile utilizzare un attributo come un vincolo. Ad esempio ...

class InsertableAttribute : Attribute 

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

Ovviamente questa sintassi non funziona, o non vorrei postare la domanda. Ma sono curioso di sapere se è possibile o meno, e come farlo.

+2

Vorrei * LOVE * se questo è stato implementato ... – tenfour

risposta

11

No. È possibile utilizzare solo classi e interfacce (base) come vincoli.

È possibile comunque fare qualcosa di simile:

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

Grazie. Questo è quello che ho pensato, ma ho pensato che valeva la pena provare. Il mio progetto non ne ha bisogno, ma ho pensato che fosse una buona informazione da sapere. Farò clic sulla casella di controllo "Accetto" tra 5 minuti quando Stack Overflow mi consente. – Ciel

+0

Prego. –

+0

Se è necessario l'attributo per alcune elaborazioni esterne, per cui un'interfaccia che controlli è il marcatore, è possibile dichiarare l'attributo nell'interfaccia e selezionare attributi ereditati. – smartcaveman

7

No. È possibile utilizzare solo le classi, interfacce, class, struct, new(), e altri parametri di tipo come vincoli.

Se InsertableAttribute specifica [System.AttributeUsage(Inherited=true)], allora si potrebbe creare una classe fittizia come:

[InsertableAttribute] 
public class HasInsertableAttribute {} 

e quindi limitare il vostro metodo come:

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

Poi T avrebbe sempre l'attributo anche se è stato proveniente solo dalla classe base. Le classi di implementazione sarebbero in grado di "scavalcare" quell'attributo specificandolo su se stessi.

+0

E altri parametri di tipo :) –

+0

@Jon Skeet Ah, ovviamente. Sapevo che stavo dimenticando qualcosa, grazie per averlo sottolineato! –

-1

No, non è possibile. La tua domanda non riguarda gli attributi, ma il design orientato agli oggetti. Si prega di leggere quanto segue per ulteriori informazioni su generic type constraint.

Io invece consiglio di fare quanto segue:

public interface IInsertable { 
    void Insert(); 
} 

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

Così che l'idea è quella di avere un'interfaccia IInsertable, e implementa questa interfaccia all'interno di una classe ogni volta che si desidera essere inseribile. In questo modo, si limiterà automaticamente l'inserimento per elementi inseribili.

Questo è un approccio più flessibile e ti darà la facilità di mantenere qualsiasi informazione uguale o diversa da un'entità a un'altra, poiché devi implementare l'interfaccia tu stesso all'interno della classe.

+0

Beh, non ho bisogno di farlo affatto. È più di una di quelle cose in cui stai codificando qualcosa, e ti colpisce come un'idea che potrebbe essere utile per qualcos'altro.In verità, se avessi bisogno di assicurare un vincolo ad un Attributo, userei semplicemente una classe fittizia. – Ciel

+0

Ho capito il tuo punto, e ci sono delle volte in cui pensi a qualcosa e ti chiedi se sia fattibile. =) Interessante domanda comunque. =) –

Problemi correlati