2009-07-14 6 views
2

Existe-t-il un moyen d'exiger qu'une classe possède un membre abstrait particulier? Quelque chose comme ceci:C#: Inherited/interface membre statique?

public interface IMaxLength 
{ 
    public static uint MaxLength { get; } 
} 

Ou peut-être ceci:

public abstract class ComplexString 
{ 
    public abstract static uint MaxLength { get; } 
} 

Je voudrais une manière appliquer qu'un type (soit par héritage ou d'une interface?) Ont un membre statique. Cela peut-il être fait?

+0

Pourquoi? – SLaks

+0

Non, ça ne peut pas. Pourquoi essayez-vous de faire cela? – SLaks

Répondre

5

Vous pouvez créer un attribut personnalisé qui permet de respecter l'exigence d'une garantie d'exécution. Ce n'est pas un exemple de code entièrement complet (vous devez appeler VerifyStaticInterfaces dans le démarrage de votre application, et vous devez remplir le TODO marqué) mais il montre l'essentiel.

Je suppose que vous posez cette question afin que vous puissiez garantir des appels basés sur la réflexion réussis aux méthodes nommées.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] 
internal sealed class StaticInterfaceAttribute : Attribute 
{ 
    private readonly Type interfaceType; 

    // This is a positional argument 
    public StaticInterfaceAttribute(Type interfaceType) 
    { 
     this.interfaceType = interfaceType; 
    } 

    public Type InterfaceType 
    { 
     get 
     { 
      return this.interfaceType; 
     } 
    } 

    public static void VerifyStaticInterfaces() 
    { 
     Assembly assembly = typeof(StaticInterfaceAttribute).Assembly; 
     Type[] types = assembly.GetTypes(); 
     foreach (Type t in types) 
     { 
      foreach (StaticInterfaceAttribute staticInterface in t.GetCustomAttributes(typeof(StaticInterfaceAttribute), false)) 
      { 
       VerifyImplementation(t, staticInterface); 
      } 
     } 
    } 

    private static void VerifyInterface(Type type, Type interfaceType) 
    { 
     // TODO: throw TypeLoadException? if `type` does not implement the members of `interfaceType` as public static members. 
    } 
} 

internal interface IMaxLength 
{ 
    uint MaxLength 
    { 
     get; 
    } 
} 

[StaticInterface(typeof(IMaxLength))] 
internal class ComplexString 
{ 
    public static uint MaxLength 
    { 
     get 
     { 
      return 0; 
     } 
    } 
} 
+1

On dirait beaucoup de travail pour quelque chose d'aussi inutile. – Janie

+0

Si vous êtes bloqué en passant des appels à travers l'API de réflexion, il vaut mieux au moins que Type.GetMethod renvoie null à un point inconnu sur la route. –

+2

Qui est le lâche qui continue de me rejeter sans explication?Si je me trompe, dis-moi au moins que je ne fais pas la même erreur à l'avenir. *Allons!* –

4

Ceci est impossible. Étant donné que les appels de méthode abstraite et virtuelle sont stockés dans un objet via sa table de pointeurs de fonction virtuelle, vous ne pouvez en aucun cas imposer une exigence d'interface sur ses membres non-instance. L'appel d'un membre statique n'a aucun objet lié à celui-ci, il n'y a donc pas de table de pointeurs virtuelle disponible.

Ce n'est pas une limitation, c'est juste comment c'est. Il n'y a aucune raison pour que cela soit jamais nécessaire ou utile. Si vous voulez appliquer une interface, vous devez le faire par l'intermédiaire des membres de l'instance.

+0

Bonne réponse, je ne sais pas pourquoi cela n'a pas été accepté. – Janie

+0

N'y a-t-il pas une différence entre une méthode 'globale', une méthode 'classe' et une méthode 'instance'? En Ruby il y a :) – xtofl

+0

Il n'existe pas de méthode "globale"; Je suis sûr que par la méthode "class" dans ruby ​​vous faites référence à des méthodes "statiques" en C++/C#/PHP/Java :) – nlaq

0

Impossible. Peut-être que vous pouvez essayer quelque chose comme ceci:

public class Base 
{ 
    public struct MyStruct 
    { 
     public static int x = 100; 
     public static int XX() 
     { 
      return 200; 
     } 
    } 
} 

public class Derived : Base 
{ 
    public void test() 
    { 
     int x = Derived.MyStruct.x; 
     int XX = Derived.MyStruct.XX(); 
    } 
} 

Références:

0

base de classe Supposons comprend un procédé statique staticmethod et une méthode d'instance InstanceMethod, qui renvoient tous les deux Int32. La classe Derived shadows deux de ces méthodes avec des méthodes de même nom qui retournent la chaîne.

Si une instance est dérivée d'une Base et appelle InstanceMethod, l'appel utilisera Base.InstanceMethod, dont le type de retour est Int32. Si l'on accepte une instance de type générique T, où T hérite de Base, et appelle InstanceMethod sur cela, il appellera également Base.InstanceMethod - encore Int32. Mais quel devrait être le sens et le type de retour de T.StaticMethod? Si on veut Base.StaticMethod, on devrait le spécifier. Quoi d'autre pourrait utilement signifier T.StaticMethod?

Questions connexes