Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84

Ограниченный доступ к изменению значения полей класса

27.09.2016, 16:21. Показов 2814. Ответов 27
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую, ценителей красоты кода.

Вот код: 2 класса «A» и «AUnit», один из которых содержит список экземпляров другого. В AUnit есть поле Name. Нужно иметь возможность менять значение этого поля, но только в том случае, если предлагаемое новое значение не используется в других экземплярах класса AUnit, которые содержаться в том же листе экземпляра класса A.
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
class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
           // И вот тут хотелось бы сменить имя а[0] но только если новое имя, не будет равно не одном из имён а[n].
            Console.ReadKey();
        }
        
    }
    class A
    {
        private List<AUnit> AUnits;
        public AUnit this[int index]
        {
            get
            {
                return AUnits[index];
            }
        }
        public A()
        {
            AUnits = new List<AUnit>() { new AUnit(), new AUnit(), new AUnit() };
        }
    }
    class AUnit
    {
        private string NamePr;
        public AUnit()
        {
            NamePr = "Default";
        }
        public string Name
        {
            get
            {
                return NamePr;
            }
        }
    }
Проблема в том, что в классе AUnit нет информации о том, что содержится в классе A, поэтому так просто в него функцию типа Rename(string name) или Set для поля не сделаешь.
Если же добавить метод в класс А, типа
C#
1
 Public Boolean Rename(int index){}
для смены поля в конкретном элементе списка, то тогда придется делать это поле так или иначе публичным (или через set что тоже самое) в классе AUnit, но тогда у нас это поле станет доступно для изменения без всякой проверки откуда угодно.
Можно конечно сделать в классе AUnit функцию, в которой одним из параметров будет массив недопустимых имён, но это какnj некрасиво.
C#
1
public Boolean Rename(String newName, String[] invalidNames){...}
Собственно абстрагируясь от языка, решением подобной проблемы был бы модификатор доступа к полю, который бы разрешал изменять поле только тому, кто содержит в себе экземпляр класса. Но тут тоже проблема – класс A содержит лист, который содержит в себе экземпляр, и кого из них считать хозяином – вопрос.
Ещё как вариант в конструктор AUnit передать указатель на экземпляр класса A, тем самым получив доступ ко всему списку. И в Set поля добавить проверку. Вариант конечно, но может есть какие-то ещё уже устоявшиеся способы решения проблемы? Задача то вроде не самая редкая.

Жду с интересом предложений.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.09.2016, 16:21
Ответы с готовыми решениями:

Изменение значения полей класса
Приветствую, путник! Есть класс: public class A; { public string B; public A(b) { ...

Значения полей класса при присвоении
public class abc { public int a; int b; public int B { set{ if(value&lt;10) a=value*2; ...

Ограниченный доступ к переменным класса
У меня есть 3 класса A, B, C. В классе A есть переменная var. Мне нужно, чтобы класс B мог получать и менять значение var, при этом C...

27
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
27.09.2016, 19:02  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Tsin Посмотреть сообщение
JustOneQuestion, вы выкатываете требования, а не описываете проблему. Вы можете сказать что вам нужно? И где же это применяется?)
Я тут в пятницу тем поднимал. Что такое Инкапсуляция?
Собствено пример - есть у нас листы, в рабочей книге екселя. Хочется переименовать лист, но нельзя чтоыб имя совпадалао с уже существующим.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
27.09.2016, 19:02
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
То тогда оно не будет меняться... a[0].Val1=3; не работает
Естественно, я же сказал - вы поставили вопрос, я на него ответил именно так, как он звучал. Если меняется вопрос - нужно менять реализацию.
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
27.09.2016, 19:09  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Естественно, я же сказал - вы поставили вопрос, я на него ответил именно так, как он звучал. Если меняется вопрос - нужно менять реализацию.
А) Да я как и остальные опоздал с ответом - вы раньше успели уточнить что ваш ответ именно под первоначальный вопрос был.

Добавлено через 1 минуту
Я там кстати чуть выше ответил на вопросы о самой задаче, ... просто скопирую на случай если пропустили и не заметили.
Цитата Сообщение от JustOneQuestion Посмотреть сообщение
Цитата Сообщение от Tsin Посмотреть сообщение
JustOneQuestion, вы выкатываете требования, а не описываете проблему. Вы можете сказать что вам нужно? И где же это применяется?)
Я тут в пятницу тем поднимал. Что такое Инкапсуляция?
Собствено пример - есть у нас листы, в рабочей книге екселя. Хочется переименовать лист, но нельзя чтоыб имя совпадалао с уже существующим.
0
27.09.2016, 19:19

Не по теме:

Цитата Сообщение от insite2012 Посмотреть сообщение
Предложите свой вариант решения, который будет удовлетворять условиям.
я сюда что, задачки решать пришел или все же велосипеды ломать? :D

0
Эксперт .NET
 Аватар для Даценд
5878 / 4755 / 2939
Регистрация: 20.04.2015
Сообщений: 8,361
27.09.2016, 19:22
JustOneQuestion,
предложу добавить в класс A из исходного сообщения метод:
C#
1
2
3
4
5
6
7
8
public void RenameAt(int index, string newName)
{
    if (AUnits.FindIndex(x => x.Name == newName) < 0)
    {
        Type t = typeof(AUnit);
        t.InvokeMember("NamePr",  BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField, null, AUnits[index], new object[] { newName });
    }
}
подключив предварительно using System.Reflection;
Использовать просто:
C#
1
a.RenameAt(1, "notDefault");
Это на первый вопрос темы. Почитаю-ка я и дополнительные условия.
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
27.09.2016, 19:46  [ТС]
Даценд
Кстати да, рефлексия это как вариант конечно. Но он настолько же изящный и законный как вламывающийся в закрытую дверь топором лесоруб... Хотя ща это модно
Но да, вариант вполне рабочий. Даже если и не слишком быстрый то не критично - менять такие значения будут не слишком часто.

Но может есть идея без нарушения инкапсуляции? Может просто классы надо как-то иначе создать. Что касается самой задачи(исходной точки изза котоырй и вопрос темы возник) я ещё раз повторю. (из другой темы скопировал)

Цитата Сообщение от JustOneQuestion Посмотреть сообщение
например что-то вроде екселя. Есть массив строк, в котрых содержиться массив слов. Массив строк содержиться в листе. Но в листе может ещё и массив картинок содержаться например, которые сами являются массивами пикселей. А массив листов это рабочая книга. И вот собственно пользовталь хочет добавлять, удалять, изменять отдельные пиксели на определённой картинке в определённом листе или изменяить определённое слово.
... ну исобственно если пользователь захочет поменять имя листа - надо чтобы была проекра нет ли ещё листа с таким же именем
0
484 / 439 / 123
Регистрация: 05.01.2010
Сообщений: 1,848
27.09.2016, 19:47
на корректность проверять лень. но компилируется мой велосипед - что-то типа описание концепции
при необходимости можно при добавлении передавать не список параметров, а экземпляр класса, куда упакованы все нужные параметры. ну и соответственно править под это остальное
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
64
65
66
        class A
        {
            public A()
            {
            }
 
            readonly Dictionary<string, IAUnit> _units = new Dictionary<string, IAUnit>();
            public IAUnit this[int index]
            {
                get
                {
                    return _units.Values.ToArray()[index];
                }
            }
            public void AddUnit(string name, string value)
            {
                if(_units.ContainsKey((name)))
                    throw new InvalidOperationException();
 
                var unit = AUnit.Create(name, value);
 
                _units.Add(name, unit);
            }
            public void Rename(string name, IAUnit u)
            {
                var unit = (AUnit) u;
                if (_units.ContainsKey(name))
                {
                    throw new ArgumentException("name");
                }
                if (!_units.ContainsValue(unit))
                {
                    throw new ArgumentException("u");
                }
                _units.Remove(u.Name);
                unit.Name = name;
                _units.Add(name, unit);
            }
 
            private class AUnit : IAUnit
            {
                private AUnit()
                {
                    Name = "Default";
                }
 
                public string Name { get; set; }
 
                public string Value { get; set; }
 
                public static IAUnit Create(string name, string value)
                {
                    return new AUnit
                    {
                        Name = name,
                        Value = value
                    };
                }
            }
        }
 
        interface IAUnit
        {
            string Name { get; } 
            string Value { get; set; }
        }
0
1 / 1 / 0
Регистрация: 01.05.2015
Сообщений: 84
27.09.2016, 22:24  [ТС]
Добавлено через 2 часа 36 минут
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
 class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
            a.Add();
            a.Add();
            a.Add();
            bool res=a[0].Rename("1");//res=true;
            res = a[1].Rename("1");//res= false;
           // a[1].Name = "1"; //Ошибку тут выдаст если раскоментить, что и нужно.
            Console.ReadKey();
        }
    }
    class A
    {
        private List<AUnit> AUnits;
        public AUnit this[int index] {get {return AUnits[index];}}
 
        public A()//ctor
        {
            AUnits = new List<AUnit>();
        }
        public void Add()
        {
            this.AUnits.Add(new AUnit(this));
        }
 
        public class AUnit
        {
            private string NamePr;
            private A Container;
 
            public AUnit()//ctor (1)
            {
                NamePr = "Default";
            }
            public AUnit(A container)//ctor (2)
            {
                NamePr = "Default";
                this.Container = container;
            }
            public string Name { get { return this.NamePr; } }
            public Boolean Rename(String newName)
            {
                Boolean res = true;
                foreach (AUnit unt in this.Container.AUnits)
                {
                    if (unt.Name == newName) res = false;
                }
                if (res) this.NamePr = String.Copy(newName);
                return res;
            }
        }
    }
Пока что этот вариант мне кажется наиболее изящным и удоволетворяющий инкапсуляции. С точки зрения же здравого смысла, передавать ссылку на то где содержиться инофрмация которая необходима для принятия решения (перименовывать или нет) тоже вполне логично. Ну и вдобавок идея передачи ссылки контейнера без всяких оговорок (о нежелательности использования и т д) описана в msdn
https://msdn.microsoft.com/ru-... 73120.aspx

Есть идеи о минусах подхода?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.09.2016, 22:24
Помогаю со студенческими работами здесь

Как получить доступ к изменению переменной из другого класса?
Это наверное клупый вопрос, но я не могу его решить! создал таблицу с тремя элементами в основе лежит массив с тремя...

Доступ к значениям полей класса
вот есть такой класс class book { private: String name; float page; float price; ...

Ограниченный доступ к сети через 5 минут теряется доступ к интернету
Добрый день,требуется помощь. У меня через роутер tp-link по wifi подключен ноутбук. Но через 5 минут исчезает доступ к интернету и не...

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

Как получить значения полей класса?
Не понимаю как получить значения класса. Вот я записываю значения в поля: public classFields() { ...


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

Или воспользуйтесь поиском по форуму:
28
Ответ Создать тему
Новые блоги и статьи
Нейросеть на алгоритме "эстафета хвоста" как перспектива.
Hrethgir 06.05.2026
На десерт, когда запущу сервер. Статья тут https:/ / habr. com/ ru/ articles/ 1030914/ . Автор я сам, нейросеть только помогает в вопросах которые мне не известны - не знаю людей которые знали-бы. . .
Асинхронный приём данных из COM-порта
Argus19 01.05.2026
Асинхронный приём данных из COM-порта Купил на aliexpress термопринтер QR701. Он оказался странным. Поключил к Arduino Nano. Был очень удивлён. Наотрез отказывается печатать русские буквы. Чтобы. . .
попытка написать игровой сервер на C++
pyirrlicht 29.04.2026
попытка написать игровой сервер на плюсах с открытым бесконечным миром. возможно получится прикрутить интерпретатор питон для кастомизации игровой логики. что есть на текущий момент:. . .
Контроль уникальности выбранного документа-основания при изменении реквизита
Maks 28.04.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРемонтСпецтехники", разработанного в КА2. Задача: уведомлять пользователя, если указанная заявка (документ-основание). . .
Благородство как наказание
Maks 24.04.2026
У хорошего человека отношения с женщинами всегда складываются трудно. А я человек хороший. Заявляю без тени смущения, потому что гордиться тут нечем. От хорошего человека ждут соответствующего. . .
Валидация и контроль данных табличной части документа перед записью
Maks 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2. Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru