#c# #access-modifiers
#c# #модификаторы доступа
Вопрос:
У меня есть double[,]
поле в классе, и важно, чтобы прямой доступ к нему не передавался извне, поэтому я создал свойство чтения-записи для управления им и создал его private
. У меня также есть вложенный struct
в классе, который я хочу сохранить как тип значения. Сама структура имеет double[,]
поле, которое, опять же, управляется соответствующим свойством чтения-записи. При определенных условиях, если свойству присвоено значение, которое недопустимо определенным образом, оно выдает пользовательское exception
. Один из аргументов, который мне нужно передать в exception
, основан на значении double[,]
поля из родительского класса, но, похоже, я не могу получить к нему доступ изнутри структуры, не создавая его public
или internal
. Я пробовал оба protected
и private
, но ни то, ни другое не работает. Есть ли другой обходной путь?
class myClass {
protected double[,] classField;
public double[,] classProperty {
get { return (double[,])classField.Clone();
set { /* code to validate the value and assign it */ }
}
private struct myStruct {
private double[,] structField;
public structProperty{
get { return (double[,])structField.Clone(); }
set {
if (!validate(value))
throw new customException(classField.getLength(1));
structField = (double[,])value.Clone();
}
}
//other fields, constructors, and methods...
}
//other fields, constructors, and methods...
}
Я рассматривал возможность доступа к свойству вместо поля, но мне понадобилось бы значение свойства для конкретного экземпляра, который поддерживает рассматриваемый экземпляр struct. Может быть, есть что-то вроде this.parent
(я пробовал это, и это не сработало, но, возможно, какой-то обходной путь, похожий по концепции)?
Комментарии:
1. могу ли я проверить: вы хотите получить доступ к MyClass.classField здесь из MyStruct?
2. да, это верно
Ответ №1:
Я предполагаю, что вы хотите myStruct
поговорить с classField
содержащим myClass
экземпляром.
Если это так: тогда проблема не в доступности — у нее уже есть доступ; проблема в области. Что касается компилятора, вложенность здесь не связана с созданием экземпляра, поэтому проблема в том, что у myStruct
нет конкретного экземпляра classProperty
, с которым можно было бы поговорить. Вот почему ошибка:
Ошибка CS0120 Для нестатического поля, метода или свойства ‘MyClass.classField’ требуется ссылка на объект
вместо доступности:
Ошибка CS0122 ‘MyClass.classField’ недоступен из-за его уровня защиты
Фактически, classField
может быть private
с точки зрения доступности: вложенный тип может видеть private
члены содержащего типа.
Что вам нужно, так это сделать что-то вроде:
private struct myStruct
{
private readonly myClass _obj;
public myStruct(myClass obj) => _obj = obj;
// ...
}
и затем вместо того, чтобы просто classField
, вам нужно сказать ему, чтобы он поговорил с _obj.classField
, чтобы сообщить ему экземпляр. Вам также потребуется сконструировать myStruct
передачу в конкретном myClass
, к которому она относится.
В принципе: this.parent
концепция, которую вы упоминаете в вопросе, не является неявной — вам нужно реализовать ее самостоятельно.
Комментарии:
1. Это не компилируется, могут ли структуры иметь конструкторы?
2. @Jerry да, они могут; Я использую синтаксис C # 7.3 здесь — если вы используете более ранний компилятор:
public myStruct(myClass obj) { _obj = obj; }
3. Я понимаю свою ошибку, он жаловался, что
stuctField
не был назначен, я работал с кодом OP. Спасибо, Марк4. lol тот факт, что вы должны явно имитировать функциональность this.parent с параметрами, действительно неудобен, но это работает. Спасибо!
5. @TaraStahler суть в том, что C # не предполагает, что ваша структура должна каким-либо образом отслеживать экземпляр, «содержащий» —
myStruct
определяется исключительно написанным вами кодом — никаких скрытых автоматических дополнительных полей. Это a: означает, что вы полностью понимаете размер / область видимости типа, который вы создаете (что может быть важно), b: означает, что он волшебным образом не становится недоступным для размытия (что было бы сделано при наличии поля, являющегося ссылкой на некоторого родителя; blittable ===T : unmanaged
для этой цели), и c: не ограничивает ваше использованиеmyStruct
экземпляров отношением 1: 1 сmyClass
экземплярами