如何存储对静态类的引用?

所以类似于:

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

我认为可以做到这一点,但编译器返回这些错误:

静态类型不能用作参数

静态类型不能用作返回类型

编辑:我知道这不起作用,但为什么? 我想StaticClass存储在内存中的某个地方,因此可以允许其他变量在同一个内存中引用它,对吧?

EDIT2:其中一个用例是这样的:

假设您收集了5个不同的静态类而没有源代码,并且它们执行通用的东西,因此您希望通过单个静态类方便地访问它们。 你可以这样做:

 public static class GenericStuff { public LinearAlgebra LinearAlgebra {get;set;} public StringUtilities String {get;set;} public GeometryOps Geometry {get;set;} } 

并使用它像:

 GenericStuff.LinearAlgebra.GetAngleBetweenVectors(v0, v1); 

您可以想到的其他一些用例。

更新 :我将利用我的精神力量来试图找出我认为你想要做的事情。

我猜你有一个静态类,你想从另一个类中访问一些方法。 是对的吗?

这样的东西,换句话说:

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

……你想做的是这样的事情?

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

如果我正确地解释了你,那么只有一种方式(我能想到)能够完成你所追求的目标。 这将是添加using声明以有效地为您的静态类型设置别名:

 // At top of file using Helper = HelperMethods; 

请注意,如果执行此操作,则表示您正在创建文件范围的别名。 没有办法只在类级别别名。


StaticClass是类的名称 。 您的StaticProperty属性需要该类的实例 ,该实例将永远不存在,因为该类是static

我真的很惊讶你甚至可以将一个属性类型化为静态类,因为它代表了一种完全不可能。 (哦等等,你做不到;那就是你说的。)

你说你想存储一个“静态类的引用”; 我必须假设你想要一个对表示类的Type对象的引用,在这种情况下你应该这样做:

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

静态类既抽象密封 (看一下生成的IL)。 因此,您无法创建它的实例,也无法将其子类化为具有子类的实例。 仅凭这种组合使您无法获得对静态类实例的引用。

现在,要以您想要的方式引用静态类,您必须在C#中使用元类 ,或者使用某种不同的别名。

要实现您今天所需的目标,您必须手动将所有方法从包装类委托给所需的静态类,或者放弃静态类型并使用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 ... } 

用法:

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

C#规范的第§8.7.12节内容如下:

不打算实例化的类,只包含静态成员的类应声明为静态类。 此类的示例是System.ConsoleSystem.Environment 。 静态类是隐式密封的,没有实例构造函数。 静态类只能与typeof运算符一起使用,并且可以访问类的元素。 特别是,静态类不能用作变量的类型或用作类型参数

因为静态类没有构造函数,所以无法实例化它。 因为它是密封的,所以不能将其子类化并创建子类的实例。 即使你可以inheritance它,你也无法调用基础构造函数,因此你仍然无法实例化它。

由于无法创建静态类类型的对象,因此将其用作返回类型是没有意义的。

由于StaticClass是类型名称而不是表达式 ,因此不能将其作为参数传递(在您的情况下,是属性设置器)。 但是,您可以使用表达式typeof(StaticClass)获取表示它的Type类的实例。

您不能存储对静态类的引用。 您只能存储对实例的引用,并且没有静态类的实例(尽管静态类可能包含实例成员)。

您应该再看一下静态类的MSDN页面。

“静态类与非静态类基本相同,但有一个区别:静态类无法实例化。换句话说,你不能使用new关键字来创建类类型的变量。因为有没有实例变量,您可以使用类名本身来访问静态类的成员。“

我想这就是你想说的:

好吧,如果你不想实例化它,那么你的C#需要更多调整。 假设您的静态类实现了属性和/或方法

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

您可以转发InstanceClass中的属性和函数定义,请注意您必须将static的类名前缀添加到要调用的方法/属性中。

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

我认为使用InstanceClass作为这样的包装器有点复杂,而且不必要。 我发现值得尝试最小化代码库中对静态类和方法的需求。 在尝试测试和调试时,它们会引起各种令人头疼的问题。

你不能这样做。 类不是自身的实例。 “狗”不是狗。 您可以将typeof(StaticClass)分配给Type类型的字段:

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

这使您可以对类型使用reflection。

我认为op想要的是一种通过你知道的“代理”轻松访问其他类的方法。

所以,假设你有一个名为MapHelpers的类:

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

而且你还有很多其他的“助手”你并不记得,只是想让它们易于使用。 因此,您希望将它们“存储”在“助手”类中,这样您就可以记住它们放在哪里。

你可以这样做:

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

并且能够通过以下方式访问您的MapHelper:

 Helpers.MapHelpers.CalculateNearLocation(pos) 

或者这样做:

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

并能够通过以下方式访问它:

 Helpers.MapHelper.CalculateNearLocation(pos) 

但是,第一种方法会在您的IDE(如果您有该集合)上发出关于通过派生类型访问静态方法的警告。

我相信使用命名空间function将是完成您尝试执行的操作的最佳方式。

LinearAlgebra.cs

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

Strings.cs

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

Geometry.cs

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

所有这些都可以从GenericStuff开始调用

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