Подтвердить что ты не робот

Как сохранить ссылку на статический класс?

Так что-то вроде:

public static class StaticClass {}

public class InstanceClass
{
    static StaticClass StaticProperty {get;set;}

    public InstanceClass()
    {
        InstanceClass.StaticProperty = StaticClass;
    }
}

Я думал, что можно это сделать, но компилятор возвращает эти ошибки:

статические типы не могут использоваться в качестве параметров

статические типы не могут использоваться как типы возврата

EDIT: Я знаю, что это не работает, но почему? Я полагаю, что 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);

Некоторые другие варианты использования, о которых вы могли подумать.

4b9b3361

Ответ 1

Обновить. Я собираюсь использовать свои психические способности, чтобы попытаться понять, что я думаю, что вы пытаетесь сделать.

Я предполагаю, что у вас есть статический класс с некоторыми методами, из которых вы хотите получить доступ из другого класса. Правильно ли это?

Что-то вроде этого, другими словами:

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);

Ответ 2

Статические классы как абстрактные, так и опечатаны (загляните в сгенерированный ИЛ). Таким образом, вы не можете создать его экземпляр, и вы не можете подклассифицировать его для экземпляров подклассов. Только эта комбинация делает невозможным когда-либо иметь ссылку на экземпляр статического класса.

Теперь, чтобы иметь ссылку на статическую работу класса так, как вы хотите, вам нужно было бы метаклассы на С# или некоторые различный вид сглаживания.

Чтобы достичь того, что вы хотите сегодня, вам придется вручную делегировать все методы из класса-оболочки в нужный статический класс или отказаться от статического ввода и использовать 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));
}

Ответ 3

Раздел §8.7.12 спецификации С# гласит:

Классы, которые не предназначены для экземпляров и которые содержат только статические члены должны быть объявлены как статические классы. Примеры таких классы System.Console и System.Environment. Статические классы неявно запечатаны и не имеют конструкторы экземпляров. Статические классы может использоваться только с типом оператора и доступа к элементам класс. В частности, статический класс не могут использоваться как тип переменной или использоваться как аргумент типа

Поскольку у статического класса нет конструкторов, вы не можете его создать. Поскольку он запечатан, вы не можете подклассифицировать его и создать экземпляр подкласса. Даже если вы можете подклассировать его, вы не сможете вызвать базовый конструктор, и поэтому вы все равно не сможете его создать.

Поскольку вы не можете создать объект типа статического класса, нет смысла использовать его как возвращаемый тип.

Так как StaticClass является именем типа, а не expression, вы не можете передать его в качестве параметра (в вашем случае, для средства настройки свойств). Однако вы можете получить экземпляр класса Type, который представляет его с выражением typeof(StaticClass).

Ответ 4

Вы не можете сохранить ссылку на статический класс. Вы можете хранить ссылки только на экземпляры, и нет экземпляров статических классов (хотя статические классы могут иметь экземпляры экземпляров).

Ответ 5

Вы должны еще раз взглянуть на страницу MSDN на статические классы.

Статический класс в основном такой же, как и нестатический класс, но есть одно отличие: статический класс не может быть создан. Другими словами, вы не можете использовать новое ключевое слово для создания переменной типа класса. Поскольку нет переменной экземпляра, вы получаете доступ к членам статического класса с помощью самого имени класса.

Ответ 6

Я думаю, это то, что вы пытаетесь сказать:

Хорошо, если вы не хотите создавать экземпляр, тогда ваш С# нуждается в немного более тонкой настройке. Предполагая, что ваш статический класс реализует свойство и/или метод

public static class StaticClass
{
    public static string StaticProperty {get; private set; }

    public static void StaticMethod() { //DoSomething }
}

Вы можете перенаправить определения свойств и функций в InstanceClass, обратите внимание, что вы должны префиксное имя класса статического класса для методов/свойств, которые вы хотите вызвать.

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

   private StaticMethod()
   {
        StaticClass.StaticMethod();
   }

   public InstanceClass()
   { }
}

Я думаю, что использование InstanceClass в качестве обертки, как это, немного сложнее и не нужно. Я обнаружил, что стоит попытаться свести к минимуму необходимость статических классов и методов в кодовой базе. При попытке тестирования и отладки они вызывают всевозможные головные боли.

Ответ 7

Вы не можете этого сделать. Класс не является примером для себя. "Собака" - это не собака. Вы можете назначить typeof(StaticClass) полю типа Type:

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

Это позволяет использовать отражение типа.

Ответ 8

То, что я считаю, - это способ легко получить доступ к другим классам через "прокси", о котором вы знаете.

Итак, скажем, у вас есть класс под названием 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 (если у вас есть этот набор) о доступе к статическим методам через производный тип.

Ответ 9

Я считаю, что использование функции пространства имен было бы лучшим способом выполнить то, что вы пытаетесь сделать.

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();