Comment stocker une référence à une classe statique?

Donc, quelque chose comme:

public static class StaticClass {} public class InstanceClass { static StaticClass StaticProperty {get;set;} public InstanceClass() { InstanceClass.StaticProperty = StaticClass; } } 

Je pensais que l’on pourrait faire cela, mais le compilateur renvoie ces erreurs:

les types statiques ne peuvent pas être utilisés comme parameters

les types statiques ne peuvent pas être utilisés comme types de retour

EDIT: Je sais que cela ne fonctionne pas, mais pourquoi? J’imagine que StaticClass est stocké quelque part dans la mémoire, de sorte que d’autres variables pourraient être autorisées à s’y référer dans la même mémoire, n’est-ce pas?

EDIT2: L’un des cas d’utilisation ressemblerait à ceci:

Supposons que vous ayez collecté 5 classes statiques différentes sans code source et qu’elles effectuent des tâches génériques. Vous souhaitez donc pouvoir y accéder facilement via une seule classe statique. Vous pourriez le faire comme:

 public static class GenericStuff { public LinearAlgebra LinearAlgebra {get;set;} public SsortingngUtilities Ssortingng {get;set;} public GeometryOps Geometry {get;set;} } 

Et utilisez-le comme:

 GenericStuff.LinearAlgebra.GetAngleBetweenVectors(v0, v1); 

Quelques autres cas d’utilisation auxquels vous pourriez penser.

Mise à jour : Je vais utiliser mes pouvoirs psychiques pour essayer de comprendre ce que je pense que vous essayez de faire.

Je suppose que vous avez une classe statique avec des méthodes auxquelles vous souhaitez accéder depuis une autre classe. Est-ce correct?

Quelque chose comme ça, en d’autres termes:

 static class HelperMethods { public static void SomeHelperMethod(); } 

… et ce que vous voulez faire est quelque chose comme ça?

 class SomeOtherClass { public void MethodThatUsesHelperMethod() { // You want to be able to have "Helper" mean "HelperMethods"? Helper.SomeHelperMethod(); } } 

Si je vous ai bien interprété, il n’y a qu’un seul moyen (que je puisse penser) d’ accomplir en quelque sorte ce que vous recherchez. Cela consisterait à append une déclaration using pour aliaser efficacement votre type statique:

 // At top of file using Helper = HelperMethods; 

Notez que si vous faites cela, vous créez un alias à l’échelle du fichier. Il n’y a aucun moyen d’aliaser les classes uniquement au niveau de la classe.


StaticClass est le nom de la classe. Votre propriété StaticProperty attend une instance de la classe, qui n’existera jamais car cette classe est static .

En fait, je suis surpris que vous puissiez même avoir une propriété typée comme une classe statique, car elle représente une impossibilité totale. (Oh, attends, tu ne peux pas faire ça, c’est ce que tu disais.)

Vous dites que vous voulez stocker une “référence à une classe statique”; Je suppose que vous voulez dire que vous voulez une référence à l’object Type représentant la classe. Dans ce cas, procédez comme suit:

 public Type StaticProperty { get; set; } // ... StaticProperty = typeof(StaticClass); 

Les classes statiques sont à la fois abstraites et scellées (jetez un coup d’œil à l’IL généré). Donc, vous ne pouvez pas en créer une instance, et vous ne pouvez pas créer une instance de sous-classes. Cette combinaison à elle seule vous empêche de jamais avoir une référence à une instance d’une classe statique.

Désormais, pour que la référence à la classe statique fonctionne comme vous le souhaitez, vous devez disposer de métaclasses en C # ou d’un autre type de pseudonyme.

Pour obtenir ce que vous voulez aujourd’hui, vous devez déléguer manuellement toutes les méthodes d’une classe wrapper à la classe statique souhaitée ou abandonner le typage statique et utiliser dynamic :

 public class StaticWrapper : DynamicObject { Type _type; public StaticWrapper(Type type) { _type = type; } public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { var method = _type.GetMethod(binder.Name, BindingFlags.Static | BindingFlags.Public, null, args.Select(a => a.GetType()).ToArray(), null); if (method == null) return base.TryInvokeMember(binder, args, out result); result = method.Invoke(null, args); return true; } // also do properties ... } 

Usage:

 public static class GenericStuff { public readonly dynamic LinearAlgebra = new StaticWrapper(typeof(LinearAlgebra)); public readonly dynamic Ssortingng = new StaticWrapper(typeof(SsortingngUtilities)); public readonly dynamic Geometry = new StaticWrapper(typeof(GeometryOps)); } 

La section §7.7.12 de la spécification C # se lit comme suit:

Les classes qui ne sont pas destinées à être instanciées et qui ne contiennent que des membres statiques doivent être déclarées en tant que classes statiques. System.Console et System.Environment sont des exemples de telles classes. Les classes statiques sont implicitement scellées et n’ont pas de constructeur d’instance. Les classes statiques ne peuvent être utilisées qu’avec l’opérateur typeof et pour accéder aux éléments de la classe. En particulier, une classe statique ne peut pas être utilisée comme type de variable ni être utilisée comme argument de type

Comme une classe statique n’a pas de constructeur, vous ne pouvez pas l’instancier. Comme il est scellé, vous ne pouvez pas le sous-classer et créer une instance de sous-classe. Même si vous pouviez créer une sous-classe, vous ne pourriez pas appeler le constructeur de base et vous ne pourrez donc toujours pas l’instancier.

Etant donné que vous ne pouvez pas créer un object du type d’une classe statique, il ne sert à rien de l’utiliser comme type de retour.

StaticClass étant un nom de type et non une expression , vous ne pouvez pas le transmettre en tant que paramètre (dans votre cas, à l’ StaticClass propriétés). Cependant, vous pouvez obtenir une instance de la classe Type qui la représente avec l’expression typeof(StaticClass) .

Vous ne pouvez pas stocker une référence à une classe statique. Vous pouvez uniquement stocker des références à des instances, et il n’y a pas d’instances de classes statiques (bien que les classes statiques puissent avoir des membres d’instance).

Vous devriez jeter un autre regard sur la page MSDN sur les classes statiques.

“Une classe statique est fondamentalement la même chose qu’une classe non statique, mais il y a une différence: une classe statique ne peut pas être instanciée. En d’autres termes, vous ne pouvez pas utiliser le nouveau mot-clé pour créer une variable du type classe. Parce qu’il y a aucune variable d’instance, vous accédez aux membres d’une classe statique en utilisant le nom de la classe elle-même. ”

Je pense que c’est ce que vous essayez de dire:

Ok, si vous ne voulez pas l’instancier, votre C # a besoin d’être peaufiné. En supposant que votre classe statique implémente une propriété et / ou une méthode

 public static class StaticClass { public static ssortingng StaticProperty {get; private set; } public static void StaticMethod() { //DoSomething } } 

Vous pouvez transférer les définitions de propriété et de fonction dans InstanceClass, en notant que vous devez préfixer le nom de classe de l’élément static aux méthodes / propriétés que vous souhaitez appeler.

 public class InstanceClass { private ssortingng StaticProperty { get { return StaticClass.StaticProperty; } } private StaticMethod() { StaticClass.StaticMethod(); } public InstanceClass() { } } 

Je pense qu’utiliser InstanceClass comme un wrapper comme celui-ci est un peu compliqué et inutile. J’ai trouvé qu’il valait la peine d’essayer de minimiser le besoin de classes et de méthodes statiques dans une base de code. Ils provoquent toutes sortes de maux de tête lorsque vous essayez de tester et de déboguer.

Tu ne peux pas faire ça. Une classe n’est pas une instance d’elle-même. “Chien” n’est pas un chien. Vous pouvez affecter typeof(StaticClass) à un champ de type Type:

 static StaticClass StaticProperty {get; set} InstanceClass.StaticProperty = typeof(StaticClass); 

Cela vous permet d’utiliser la reflection sur le type.

Je pense que l’op veut, c’est un moyen d’accéder facilement à d’autres classes via un “proxy” que vous connaissez.

Alors, disons que vous avez une classe appelée MapHelpers:

 public class MapHelper { public static ssortingng CalculateNearLocation (Vector3 position){...} } 

Et vous avez beaucoup d’autres “Helpers” dont vous ne vous souvenez pas vraiment et que vous voulez juste qu’ils soient facilement accessibles. Et ainsi, vous voulez les “stocker” dans votre classe “Helpers”, juste pour vous rappeler où vous les avez mis.

Vous pouvez soit faire ceci:

 public class Helpers { public class MapHelpers : MapHelper{} } 

Et pouvoir accéder à votre MapHelper via:

 Helpers.MapHelpers.CalculateNearLocation(pos) 

Ou faire ceci:

 public partial class Helpers { } public partial class Helpers { public class MapHelper { public static ssortingng CalculateNearLocation (Vector3 position){...} } } 

Et pouvoir y accéder via:

 Helpers.MapHelper.CalculateNearLocation(pos) 

Cependant, la première méthode vous donnera un avertissement sur votre IDE (si vous avez cet ensemble) sur l’access aux méthodes statiques via un type dérivé.

Je pense que l’utilisation de la fonction d’espace de nommage serait le meilleur moyen d’accomplir ce que vous essayez de faire.

LinearAlgebra.cs

 namespace GenericStuff { public static class LinearAlgebra { public static TypeOfResult Function() { ... } } } 

Ssortingngs.cs

 namespace GenericStuff { public static class Ssortingngs { public static TypeOfResult Function() { ... } } } 

Geometry.cs

 namespace GenericStuff { public static class Geometry { public static TypeOfResult Function() { ... } } } 

Tous pouvant être invoqués à partir de GenericStuff

 var s = GenericStuff.Ssortingngs.Random(7); var identity = GenericStuff.LinearAlgebra.Identity(3); var square = GenericStuff.Geometry.Square(5); var area = square.Area();