Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
1 / 1 / 0
Регистрация: 17.09.2024
Сообщений: 3

Ссылка на значимый тип и доступ для чтения

17.09.2024, 13:42. Показов 717. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день товарищи, помогите решить одну проблемку.
Есть два класса Sensor и Connector, упрощенно они выглядят так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Сonnector
{
    public bool Value { get; protected set; }
    //...
}
 
public class Sensor
{
    public Сonnector HasTarget { get; protected set; } = new();
 
    protected void Start()
    {
        HasTarget .Value = false; //Нет доступа из Sensor
    }
    //...
}
Нужно дать возможность экземпляру Sensor менять HasTarget.Value из своих методов, то есть условно работать как со своим собственным свойством, но для всех остальных оно должно быть только для чтения, что бы сохранить инкапсуляцию.
Другими словами экземпляр класса Сonnector должен осуществлять доступ для чтения к Value для всех желающих, но менять значение Value должен только экземпляр Sensor у которого есть на него ссылка. Надеюсь объяснил понятно)

П.С. Вынести само свойство bool HasTarget в Sensor можно и тогда к нему будет доступ изнутри Sensor, но тогда надо заставить Сonnector транслировать его наружу для чтения(потому что основная задача класса Сonnector соединяться с теми кому его как раз нужно передать). Но как сделать ссылку на значимый тип тогда?
В общем прошу помощи...
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
17.09.2024, 13:42
Ответы с готовыми решениями:

Как определить ссылку на значимый тип
Допустим в классе A есть статическое поле static int P; как определить переменную int L в Main Так что бы адрес &L==&A.P? Простое...

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

Доступ только для чтения
static void Main(string args) { string name = "Nikita"; name = "."; } невозможно...

8
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,228
17.09.2024, 14:09
Цитата Сообщение от GlaM4X Посмотреть сообщение
//Нет доступа из Sensor
Sensor и Connector определены в одной сборке?

Добавлено через 1 минуту
Помимо основных существуют гибридные модификаторы доступа:
1. protected internal
2. private protected

Если в одной сборке, то вам поможет первый модификатор.

Добавлено через 1 минуту
Если вы разрабатываете какой-то функционал, и знаете как работать с типами в вашей сборке правильно, то нет ничего страшного открывать доступ к членам внутри текущей сборки. Здесь вы берете как бы ответственность на себя.

Добавлено через 22 секунды
C#
1
2
3
4
5
public class Сonnector
{
    public bool Value { get; protected internal set; }
    //...
}
Добавлено через 3 минуты
По той же схеме можно объявить свой internal interface, доступный только внутри текущей сборки. И заставить коннектор реализовать его, для мутации своего состояния.
А Sensor будет принимать ссылку на этот интерфейс.

Добавлено через 10 минут
Цитата Сообщение от IamRain Посмотреть сообщение
А Sensor будет принимать ссылку на этот интерфейс.
Либо вот так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
internal interface IConnectorMutator
{
    void MutateValue(bool newValue);
}
 
public class Сonnector : IConnectorMutator
{
    public bool Value { get; protected set; }
    //...
    public void MutateValue(bool newValue)
    {
        Value = newValue;
    }
}
 
 
public class Sensor
{
    private readonly Сonnector _connector;
    private readonly IConnectorMutator _mutator;
    
    public bool HasTarget => _connector.Value;
 
    public Sensor(Сonnector connector)
    {
        _connector = connector;
        _mutator = connector;
    }
 
    protected void Start()
    {
        _connector.Value = false; //Нет доступа из Sensor
        _mutator.MutateValue(false); // а тут есть доступ
    }
    //...
1
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
17.09.2024, 16:08
Ну, можно такой финт ушами, но хотелось бы понимать "зачем". Если закрываете внутри либы -- достаточно internal.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Сonnector
{
    public bool Value { get; protected set; }
 
 
    public Сonnector(Action<Action<bool>> regSetter)
    {
        regSetter(x => Value = x);
    }
}
 
public class Sensor
{
    private Action<bool> setValue;
 
    public Сonnector HasTarget { get; protected set; }
 
    public Sensor()
    {
        HasTarget = new(a => setValue = a);
    }
 
    protected void Start()
    {
        setValue(false);
    }
}
Добавлено через 1 минуту
P.S. интересно, есть ли смысл просить разрабов языка вводить out\ref для конструкторов....

Добавлено через 3 минуты
p.p.s. вообще kolorotur (или кто-то из местных) когда-то создавал тему с примерами как это делать, но я естественно ничего не запомнил и как-то не сохранил линк на неё....
1
1 / 1 / 0
Регистрация: 17.09.2024
Сообщений: 3
18.09.2024, 12:53  [ТС]
Цитата Сообщение от IamRain Посмотреть сообщение
Sensor и Connector определены в одной сборке?
Цитата Сообщение от Wolfdp Посмотреть сообщение
Если закрываете внутри либы -- достаточно internal.
Это проект на Unity и насколько я понимаю она включает все пользовательские скрипты в одну сборку(хотя глубоко не разбирался), поэтому вопрос инкапсуляции один из главных. Да я и сам могу забыть через месяц-два и дернуть то что не нужно, а если к проекту подключиться другой программист, он точно дернет)) поэтому важно скрыть все лишнее. Это значит internal не вариант к сожалению... В любом случае спасибо за предложенные варианты и потраченное время)
Я вот думал-думал и пока такое придумал, вроде бы работает, но не точно)
1. Добавил класс ValueContainer что бы иметь возможность ссылаться на значимые типы
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ValueContainer<T>
{
    public T Value { get; set; }
 
    public ValueContainer() { }
 
    public ValueContainer(T value)
    {
        Value = value;
    }
 
    /*public static implicit operator T(ValueContainer<T> container)
    {
        if (container == null) return default(T);
        return container.Value;
    }*/
}
2. В Sensor прописал ValueContainer<bool> HasTarget (логически это свойство этого класса, пусть тут и лежит), сделал его полностью protected что бы его не было видно наружу, вроде бы инкапсуляция есть.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Sensor
{
    protected ValueContainer<bool> HasTarget        { get; set; } = new();
 
    public Сonnector HasTargetСonnector             { get; protected set; }
 
    protected override void Start()
    {
        HasTargetСonnector = new(HasTarget);
 
        HasTarget.Value = false; //работает
        HasTargetСonnector.Value = false; //не работает, только для чтения
    }
}
3. В Сonnector тоже прописал ValueContainer<bool> и получаю его в конструкторе, которое protected и только для чтения. Для получения значения наружу Value => Container.Value
C#
1
2
3
4
5
6
7
8
9
10
public class Сonnector
{
    protected ValueContainer<bool> Container       { get; }
    public bool Value                              => Container.Value;
 
    public LogicСonnector(ValueContainer<bool> container)
    {
        Container = container;
    }
}
Хотелось сделать простое и быстрое решение, потому экземпляров будут тысячи с десятками тысяч обращений в секунду, не знаю как будет работать посмотрим, если есть замечания жду)

П.С. для чего вообще это все, Sensor это тестовая деталь, Connector соединение между деталями для передачи сигналов
Вложения
Тип файла: mp4 Video_2024-09-16_110820.mp4 (1.80 Мб, 9 просмотров)
1
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,228
18.09.2024, 13:31
GlaM4X, пойдет. Вполне себе работающее решение.

Добавлено через 2 минуты
Главное, чтобы ссылка на ValueContainer<bool> была только у экземпляра Sensor.
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
18.09.2024, 13:46
Цитата Сообщение от GlaM4X Посмотреть сообщение
Это проект на Unity и насколько я понимаю она включает все пользовательские скрипты в одну сборку(хотя глубоко не разбирался), поэтому вопрос инкапсуляции один из главных
Абсолютно нет. Такая инкапсуляция имеет смысл когда у вас либо отдельная сборка в солюшене из набора проектов, либо когда вы пишете либу. Есть ещё варианты когда логически нужно запретить кому-либо менять состояние объекта, кроме владельца.

Но лично меня смущает сам объект Сonnector -- он только имеет состояние Value? Если да -- он бессмысленный. Правильнее будет просто создать интерфейс IConnector, который имеет свойство только для чтения, и реализовать его в Sensor. Это в свою очередь решит вопрос производительности, т.к. будете работать напряму, а не через посредника.
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,228
18.09.2024, 13:50
Цитата Сообщение от Wolfdp Посмотреть сообщение
Правильнее будет просто создать интерфейс IConnector, который имеет свойство только для чтения, и реализовать его в Sensor.
Коннектор ятп - это отдельный объект, поэтому нужна отдельная абстракция.
Цитата Сообщение от GlaM4X Посмотреть сообщение
Connector соединение между деталями для передачи сигналов
0
1 / 1 / 0
Регистрация: 17.09.2024
Сообщений: 3
18.09.2024, 14:19  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
Но лично меня смущает сам объект Сonnector -- он только имеет состояние Value? Если да -- он бессмысленный. Правильнее будет просто создать интерфейс IConnector, который имеет свойство только для чтения, и реализовать его в Sensor. Это в свою очередь решит вопрос производительности, т.к. будете работать напряму, а не через посредника.
Я упрощал класс для лучшего понимания вопроса, у него своя внутренняя(которая еще не дописана логика) на данный момент выглядит так
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public abstract class Сonnector
{
    public Сonnector ConnectedConnector         { get; protected set; }
    public ConnectorTypes ConnectorType         { get; protected set; }
    public SignalTypes SignalType               { get; protected set; }
 
    public bool IsConnected                     => ConnectedConnector != null;
 
 
    public virtual bool Connect(Сonnector otherСonnector)
    {
        if (otherСonnector.ConnectedConnector == this)
        {
            ConnectedConnector = otherСonnector;
            return true;
        }
 
        //if (IsConnect || otherСonnector.IsConnect) return false;
 
        if (otherСonnector.SignalType == SignalType && otherСonnector.ConnectorType != ConnectorType)
        {
            ConnectedConnector = otherСonnector;
            otherСonnector.Connect(this);
            return true;
        }
        else return false;
    }
}
 
public class LogicСonnector : Сonnector
{
    protected ValueContainer<bool> Container    { get; }
    public bool Value                           => Container.Value;
 
 
    public LogicСonnector(ValueContainer<bool> container, ConnectorTypes connectorType)
    {
        ConnectorType = connectorType;
        SignalType = SignalTypes.Logic;
        Container = container;
    }
 
    public override bool Connect(Сonnector otherСonnector)
    {
        if (otherСonnector is not LogicСonnector conn) return false;
        
        return false;
    }
}
 
public enum ConnectorTypes
{
    Input,
    Output
}
 
public enum SignalTypes
{
    Logic,
    Numeric,
    //Power,
    Other
}
Плюс при объявлении на нем атрибуты висят для автоматического создания контролов интерфейса, которые через рефлексию настраиваются его внутренние параметры
C#
1
2
[OutputLogicConnectorControl(3)]
public LogicСonnector HasTargetСonnector                { get; protected set; }
Я просто конкретизировал задачу выкинув все лишнее))
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
18.09.2024, 14:53
Цитата Сообщение от GlaM4X Посмотреть сообщение
у него своя внутренняя(которая еще не дописана логика)
Тогда смысл переводить на интерфейс нет. Единственное что меня смущает -- что container по факту нужно создавать извне. Я бы сделал наверное по финалу так

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LogicСonnector
{
    protected ValueContainer<bool> Container { get; }
    public bool Value => Container.Value;
 
    private LogicСonnector(ValueContainer<bool> container)
    {
        Container = container;
    }
 
    public LogicСonnector Create(out ValueContainer<bool> container)
    {
        container = new ValueContainer<bool>();
        var connector = new LogicСonnector(container);
        return connector;
    }
}
Смысл в том чтобы гарантировать новый внутренний контейнер, а не возможно закинуть хз какой извне. Причем даже если бы я таки остановился на делегатах (идея с отдельным контейнером мне не очень, но тут аргументов за/против нет), то тоже подправил на такое

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Сonnector
{
    public bool Value { get; private set; }
 
 
    private Сonnector()
    { }
 
    public static Сonnector Create(out Action<bool> setter)
    {
        var connector = new Сonnector();
        setter = v => connector.Value = v;
        return connector;
    }
}
 
public class Sensor
{
    private Action<bool> setValue;
 
    public Сonnector HasTarget { get; protected set; }
 
    public Sensor()
    {
        HasTarget = Сonnector.Create(out setValue);
    }
 
    protected void Start()
    {
        setValue(false);
    }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.09.2024, 14:53
Помогаю со студенческими работами здесь

Доступ только для чтения
Привет Текущий пользователь запускает приложение, на клиенте получаем SID текущего пользователя, ищем в базе данных ACCESS...

Тип файла для сохранения и чтения
Добрый день, уважаемые пользователи. Мне понадобился совет. Моя программа отправляет на определенные сайты POST запросы, в самой программе...

Как запретить доступ для чтения с диска C для определенной программы?
День добрый ! Собственно, есть к примеру, утилита без настроек, которая ищет информацию по всему ПК. Нужно ограничить ей область...

Доступ по указателю только для чтения
Мое почтение, джентльмены. Возможно ли сделать доступ по указателю к структуре в классе - только для чтения? Сама структура может...

Доступ только для чтения исправление
Не могу понять, каким образом можно изменить параметр в Graphics Dpi.X Такая ошибка появляется: Ошибка CS0200 Невозможно присвоить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США. Нашел на реддите интересную статью под названием «Кто-нибудь знает, где получить бесплатный компьютер или. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru