class A
{
protected int _p;
public int P
{
get
{
return 1;
}
}
}
class B : A
{
public int P
{
set
{
_p = value;
}
}
}
class Program
{
static void Main(string[] cmd)
{
B b = new B();
int i = b.P; // A.P (get)
b.P = 3; // B.P (set)
}
}
Можно ли как то добиться такого? Понятно, что в B можно сделать new public int P { get { return base.P; } } ... А как то по проще?
class A
{
protected int _p;
public virtual int P
{
get
{
return 1;
}
set { }
}
}
class B : A
{
public override int P
{
set
{
_p = value;
}
}
}
Re[2]: C# properties
От:
Аноним
Дата:
27.08.10 08:15
Оценка:
Здравствуйте, QrystaL, Вы писали:
QL>
QL> class A
QL> {
QL> protected int _p;
QL> public virtual int P
QL> {
QL> get
QL> {
QL> return 1;
QL> }
QL> set { }
QL> }
QL> }
QL> class B : A
QL> {
QL> public override int P
QL> {
QL> set
QL> {
QL> _p = value;
QL> }
QL> }
QL> }
QL>
Спасибо, но хотелось бы еще что-бы компилятор не давал менять A.P т.е:
class A
{
protected int _p;
public virtual int P
{
get { return 1; }
set { throw new NotSupportedException(); }
}
}
Re[4]: C# properties
От:
Аноним
Дата:
27.08.10 08:26
Оценка:
Здравствуйте, QrystaL, Вы писали:
А>>A a = new A(); А>>a.P = 5; // Compiler error
QL>Так не получится. Как вариант, можно написать
QL>
QL> class A
QL> {
QL> protected int _p;
QL> public virtual int P
QL> {
QL> get { return 1; }
QL> set { throw new NotSupportedException(); }
QL> }
QL> }
QL>
S>Когда коллеги станут вас убивать, меня не выдавайте, ок?
Насколько я понял, автор изначально от этого способа отказался: "Понятно, что в B можно сделать new public int P { get { return base.P; } } ... А как то по проще?"
Хотя не совсем понятно, какую задачу он вообще решает
Re[3]: C# properties
От:
Аноним
Дата:
27.08.10 09:17
Оценка:
Здравствуйте, QrystaL, Вы писали:
S>>Когда коллеги станут вас убивать, меня не выдавайте, ок? QL>Насколько я понял, автор изначально от этого способа отказался: "Понятно, что в B можно сделать new public int P { get { return base.P; } } ... А как то по проще?" QL>Хотя не совсем понятно, какую задачу он вообще решает
Именно!
Задача можно кратко объяснить так: Класс A — Read-Only, a B — Read-Write. Не хочется дублировать код, поэтому последний наследуется от первого.
Здравствуйте, QrystaL, Вы писали:
QL>Насколько я понял, автор изначально от этого способа отказался: "Понятно, что в B можно сделать new public int P { get { return base.P; } } ... А как то по проще?"
Здравствуйте, Uzzy, Вы писали:
U>Здравствуйте, Аноним, Вы писали:
U>Меняйте дизайн, не там решаете проблему.
Хмм... Ок, что Вы посоветуете?
Опишу задачу по подробнее:
Есть класс, например User.
Есть два типа потребителей этого класса — одним можно только читать, другим читать и менять.
Соответсвенно, пишется два класса — UserBaseRO, со свойствами только get, и наследник User : UserBaseRO со свойствами get и set.
Логика в get идеентична в обоих классах. Очень хочется иметь защиту от изменения свойств UserBaseRO на уровне компилятора.
Как можно это реализовать правильно\хорошо\красиво?
public abstract class Base
{
private int p;
protected int GetP()
{
return p;
}
protected void SetP(int value)
{
p = value;
}
}
public class User : Base
{
public int P
{
get { return GetP(); }
set { SetP(value); }
}
}
public class ReadOnlyUser : Base
{
public int P
{
get { return GetP(); }
}
}
Здравствуйте, Аноним, Вы писали:
U>>Меняйте дизайн, не там решаете проблему.
А>Хмм... Ок, что Вы посоветуете? А>Опишу задачу по подробнее: А>Есть класс, например User. А>Есть два типа потребителей этого класса — одним можно только читать, другим читать и менять.
Речь идёт обо всех свойствах? Подойдёт ли такой вариант:
interface IUser
{
int Property1 { get; }
string Property2 { get; }
}
classs User : IUser
{
public int Property1 { get; set; }
public string Property2 { get; set; }
}
Соответственно, тем, кто может только читать, отдаётся интерфейс, остальные могут использовать класс. Если всем нужны непременно экземпляры классов и свойств [относительно] много, ИМХО, более правильным решением было бы написание одного класса с get и set, флагом ReadOnly и бросанием InvalidOperationException из сеттеров ридонли-объекта. Так, например, спроектированны классы в System.Globalization Namespace.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Соответственно, тем, кто может только читать, отдаётся интерфейс, остальные могут использовать класс.
Лазейка для изменения свойства останется
IUser iUser = new User();
((iUser)user).Property1 = 1;
Если имеется попытка закрыть возможность изменения значения свойства на этапе компиляции, то в рантайме и подавно такую возможность давать нельзя
Здравствуйте, Uzzy, Вы писали:
_FR>>Соответственно, тем, кто может только читать, отдаётся интерфейс, остальные могут использовать класс. U>Лазейка для изменения свойства останется
Она имеется всегда
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, Uzzy, Вы писали:
_FR>>>Соответственно, тем, кто может только читать, отдаётся интерфейс, остальные могут использовать класс. U>>Лазейка для изменения свойства останется
_FR>Она имеется всегда
Ну можно вынести интерфейсы доступа в прокси-объекты и отдавать их. Но вот надо ли всё это, я лично сомневаюсь.