использование статического свойства абстрактного класса внутри универсального класса, который работает на подклассах абстрактного класса - PullRequest
0 голосов
/ 26 августа 2010

У меня вопрос по поводу следующего кода:

abstract class a
{
    public static string x;
}



class b<c> where c : a
{
    public void f()
    {
        c.x=10;
    }
}

Этот код не компилируется.Я получаю ошибку при утверждении cx = 10;,Проблема заставляет его выглядеть так, как будто условие where c:a не оказывает никакого влияния вообще. Может кто-нибудь объяснить, почему это ошибка?Не правда ли, что x совместно используется как статический член всеми потомками a?И есть ли способ обойти эту проблему?

Я пытаюсь добиться этого: у меня есть подкласс a, все объекты которого имеют общее свойство, и это свойство должно быть установлено через f () в родовом классе б.Это нормально, если я заменю рассматриваемое утверждение топором = 10?Если нет, чем ax отличается от cx (или hx, где h подкласс a)?

Ответы [ 3 ]

8 голосов
/ 26 августа 2010

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

class P
{
    public static string X;
}

class Q : P { }

class R : P { }

вы можете получить доступ с P.X через P.X или Q.X или R.X, но это все еще то же поле:

P.X = "Hello";
Q.X = "World";
Console.WriteLine(R.X);  // prints "World"

Как вы обнаружили, вы не можете сделать это с помощью параметров общего типа.Но доступ к X, хотя параметр типа на самом деле не имеет большого смысла, потому что все, что вы изменяете, это P.X, который вы пишете напрямую без параметра универсального типа.


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

abstract class A
{
    public abstract string X
    {
        get;
    }
}

class A1 : A
{
    public override string X
    {
        get { return "A1"; }
    }
}

class A2 : A
{
    public override string X
    {
        get { return "A2"; }
    }
}

Если вы хотите связатьбит информации с типом (не экземпляр), вы можете определить статическое поле, которое параметризовано с типом, используя универсальный класс:

class Info<T>
{
    public static string X;
}

Info<A1>.X = "Hello";
Info<A2>.X = "World";

Console.WriteLine(Info<A1>.X);  // prints "Hello"
Console.WriteLine(Info<A2>.X);  // prints "World"

Как насчет этого?

abstract class Job
{
    public abstract string ExePath
    {
        get;
    }

    public void Execute(string[] args)
    {
        Console.WriteLine("Executing {0}", this.ExePath);
    }
}

abstract class Job<T> where T : Job<T>
{
    public override string ExePath
    {
        get { return JobInfo<T>.ExePath; }
    }
}

class ConcreteJob1 : Job<ConcreteJob1> { }

class ConcreteJob2 : Job<ConcreteJob1> { }

static class JobInfo<T> where T : Job<T>
{
    public static string ExePath;
}

static class JobInfoInitializer
{
    public static void InitializeExePaths()
    {
        JobInfo<ConcreteJob1>.ExePath = "calc.exe";
        JobInfo<ConcreteJob2>.ExePath = "notepad.exe";
    }
}

Это близко соответствует процессу, который вы описываете в своем комментарии.Это должно работать, хотя я не разработал бы настраиваемую модель Job.

0 голосов
/ 26 августа 2010

Это ошибка, потому что c - это параметр общего типа , , а не тип . Статические члены доступны только через типы.

Хорошо, если я заменю утверждение в вопросе с a.x = 10? Если нет, чем a.x отличается от c.x (или h.x где h подкласс a)?

Вы действительно можете заменить утверждение на a.x=10;. Как вы заметили, это означает, что b.x, c.x и d.x также будут равны 10.

0 голосов
/ 26 августа 2010

Если вы хотите иметь разные статические хранилища для каждого подкласса, но хотите иметь возможность доступа к состоянию из экземпляра, полиморфно, вы можете сделать что-то вроде этого:

abstract class A
{
    public abstract string X { get; set; }
}

class D : A
{
    private static string _x;

    public override string X
    {
        get { return _x; }
        set { _x = value; }
    }
}

Различные подклассы A могут обеспечивать собственную реализацию X, включая использование резервного статического хранилища, если это желательно. Обратите внимание, что это не обязательно хорошая идея, так как такое сложное глобальное состояние (притворяющееся свойством экземпляра) может затруднить понимание и поддержание вашего кода.

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