Доступ к константному значению из экземпляра в C#

Мне нужно получить доступ к значению класса const в экземпляре этого класса, не зная типа класса, а также иметь доступ к нему в самом классе. Как я могу это сделать?

Пример того, чего я хочу достичь:

public abstract class A { }

public class B : A
{
    public const int X = 50;
}
...
A b = new B();
b.X ???

Это очень неполно, но я хочу добиться доступа к константе X B из переменной типа A через полиморфизм (если это имеет смысл).

Это один из способов, которым я пытался добиться этого:

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

public class B : A
{
    public const int X = 50;
    public override int X { get { return B.X; } } // or return 50;
}

Однако проблема заключается в том, что C# не позволит этому скомпилироваться из-за двойного определения X в B. Итак, как мне это сделать? Есть ли способ лучше? Или мой единственный вариант - назвать их по-другому?


person Sh4rK    schedule 15.05.2013    source источник
comment
Что не так с подходом public override int X {...? если вы используете { get { return 50; }}, это работает.   -  person MAV    schedule 16.05.2013
comment
@MAV Нет, это не работает из-за нескольких определений X в B.   -  person Sh4rK    schedule 16.05.2013
comment
Вы должны удалить public const int X = 50; и просто переопределить.   -  person MAV    schedule 16.05.2013
comment
Да, я не уверен, почему вы чувствуете необходимость иметь значение const. Это какое-то навязанное требование?   -  person itsme86    schedule 16.05.2013
comment
Мне также нужно иметь значение в классе, чтобы я мог получить к нему доступ, как B.X.   -  person Sh4rK    schedule 16.05.2013
comment
@Sh4rK Я не думаю, что можно заставить классы реализовать такую ​​константу. См. этот ответ.   -  person MAV    schedule 16.05.2013
comment
Дело не в том, чтобы заставить их реализовывать константы, а в том, чтобы иметь константы и переменные экземпляра с одинаковыми именами.   -  person Sh4rK    schedule 16.05.2013
comment
Вам нужно обновить значение X? если да, выберите решение статического поля. Если вам просто нужна константа, ваш код работает так. int xvalue = B.X; и вам не нужна переменная любого типа, константа есть константа.   -  person terry    schedule 16.05.2013


Ответы (2)


Что-то вроде этого должно сделать вас:

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

class B : A
{
    public override int X { get { return 5 ; } }
}

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

person Nicholas Carey    schedule 16.05.2013
comment
Как я писал в других комментариях, я должен иметь доступ к X в самом классе B. - person Sh4rK; 16.05.2013
comment
@Sh4rK: Что вы подразумеваете под доступом X к самому классу B? Как ClassNameB.X? - person Ken Kin; 16.05.2013
comment
@KenKin Да, как статическая переменная или константа. - person Sh4rK; 16.05.2013
comment
@Sh4rK: Значит, вы не хотите, чтобы к X обращались с экземпляром? - person Ken Kin; 16.05.2013
comment
@KenKin Я хочу иметь доступ к X как с экземпляром, так и без него. - person Sh4rK; 16.05.2013
comment
@ Sh4rK ... в таком случае ты СОЛ. Член не может быть одновременно членом класса (статическим) и членом экземпляра. Методы экземпляра могут ссылаться на статические члены, но статические члены не могут ссылаться на члены экземпляра. Вероятно, вы могли бы использовать отражение, чтобы получить желаемое поведение, но это кажется... неоптимальным. Какую именно проблему вы пытаетесь решить? - person Nicholas Carey; 16.05.2013

То, что вы хотите, может быть статическим членом только для чтения:

public abstract class A {
    public static readonly int X=100;
}

public class B: A {
    public static readonly int X=50;
}

Посмотрите только для чтения. Статический элемент только для чтения можно считать константой времени выполнения.

Если вы ищете переопределяемый постоянный/статический элемент, вы можете взглянуть на Как реализовать виртуальные статические свойства?; что невозможно даже в C#.

person Ken Kin    schedule 16.05.2013
comment
@Sh4rK: Вы имеете в виду, что хотите иметь все A.X и a.X и B.X и b.X, где X существует либо с классом, либо с экземпляром, и применять к обоим классам? - person Ken Kin; 16.05.2013
comment
Нет, я хочу B.X, а с экземпляром B, b.X и a.X. - person Sh4rK; 16.05.2013
comment
@Sh4rK: B.X и b.X разные; вы не можете определить элемент экземпляра с тем же именем, что и член, не являющийся экземпляром. - person Ken Kin; 16.05.2013
comment
тогда поищу другое решение - person Sh4rK; 16.05.2013
comment
@Sh4rK: Просто дайте им разные имена и постарайтесь не использовать обходной путь. Эта проблема указывает на то, что вы столкнулись с плохой практикой проектирования. - person Ken Kin; 16.05.2013