Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
5 / 3 / 2
Регистрация: 27.04.2022
Сообщений: 60

Создание экземпляров классов исключительно как полей/свойств других объектов

03.09.2025, 00:16. Показов 2336. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день!
Допустим, имеется два класса
C#
1
2
3
4
5
6
7
8
    class SomeClass
    {
 
    }
    class ClassProperty
    {
 
    }
Каким образом можно реализовать ситуацию, чтобы экземпляры класса ClassProperty нельзя было создать вне экземпляров класса SomeClass?
Пока мне видится описывать SomeClass и ClassProperty в отдельной .dll и делать internal ClassProperty (если это так работает вообще). Но ClassProperty может понадобиться и для совершенно других классов, описываемых в других сборках, про существование которых я ещё не знаю.
Наверняка имеются стандартные инструменты/шаблоны мне пока неизвестные.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
03.09.2025, 00:16
Ответы с готовыми решениями:

Связывание значений полей и свойств объектов разных классов
Здравствуйте. Нужен совет. Имеется переменная типа SolidColorBrush. Есть объект другого класса, и я...

Необходимо создать несколько экземпляров класса, содержащего экземпляры других классов, и выдать их на экран
Заданы классы, в один из классов встроены поля – экземпляры других классов. Описать все классы...

В классе данных определите переменные экземпляров.Значения переменных экземпляров должны быть введены с клавиатуры
В классе данных определите переменные экземпляров.Значения переменных экземпляров должны быть...

21
Эксперт .NET
 Аватар для Wolfdp
3785 / 1762 / 371
Регистрация: 15.06.2012
Сообщений: 6,535
Записей в блоге: 3
03.09.2025, 02:03
Для того чтобы расшарить internal в другую сборку можно использовать InternalsVisibleToAttribute
0
2393 / 1913 / 763
Регистрация: 27.07.2012
Сообщений: 5,557
03.09.2025, 10:02
Цитата Сообщение от power_factor Посмотреть сообщение
Каким образом можно реализовать ситуацию, чтобы экземпляры класса ClassProperty нельзя было создать вне экземпляров класса SomeClass?
Цитата Сообщение от power_factor Посмотреть сообщение
Но ClassProperty может понадобиться и для совершенно других классов, описываемых в других сборках, про существование которых я ещё не знаю.
По-моему, это две противоречащих друг другу установки.

Цитата Сообщение от power_factor Посмотреть сообщение
делать internal ClassProperty
internal - это ограничение области видимости внутри сборки. В применении этого модификатора к всему классу смысла особого нет, так как внутри сборки все типы этой сборки и так видны.
0
151 / 135 / 29
Регистрация: 02.07.2013
Сообщений: 962
03.09.2025, 11:20
C#
1
2
3
4
5
6
7
    class SomeClass
    {
       private class ClassProperty
      {
 
      }
    }
0
5 / 3 / 2
Регистрация: 27.04.2022
Сообщений: 60
03.09.2025, 12:05  [ТС]
Цитата Сообщение от John Prick Посмотреть сообщение
По-моему, это две противоречащих друг другу установки.
Попробую объяснить свои рассуждения. Допустим, есть классы Воздух, Вода и Температура. Экземпляр класса Температура можно создать в экземпляре классов Воздух и Вода, но вот вне их нельзя, так как не может быть температуры "ничего".
Есть ощущение, что должны быть какие-то специальные паттерны агрегации/композиции для подобных задач.

Добавлено через 4 минуты
Цитата Сообщение от golosalex Посмотреть сообщение
C#
1
2
3
4
5
6
7
    class SomeClass
    {
        private class ClassProperty
        {
 
        }
    }
В этом случае при создании в SomeClass свойства public ClassProperty classProperty { get; } = new(); компилятор выдаёт ошибку CS0053.
Требуется что-то вроде такого:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
    class SomeClass1
    {
        class ClassProperty {}
    }
    class SomeClass2
    {
        class ClassProperty {}
    }
/*ещё много других классов с ClassProperty*/
    class SomeClassN
    {
        class ClassProperty {}
    }
При этом нужно обеспечить ситуацию, чтобы:
- во-первых, описатьClassProperty где-то в одном месте один раз. Думал создать public abstract class ClassPropertyBase и от него наследоваться, но ведь его всё равно нужно будет реализовывать в каждом SomeClass.
- во-вторых, объекты класса ClassProperty могли создаваться только внутри объектов SomeClass. Т. е., чтобы было нельзя сделать вот так:
C#
1
2
3
4
private static void Main()
{
    ClassProperty classProperty = new();
}
0
151 / 135 / 29
Регистрация: 02.07.2013
Сообщений: 962
03.09.2025, 14:03
Цитата Сообщение от power_factor Посмотреть сообщение
Нужно обеспечить ситуацию, чтобы:
так нельзя, если какой-то тип "виден" в классе, то он будет доступен для использования и как поле класса, и как тип для локальной переменной.
0
2393 / 1913 / 763
Регистрация: 27.07.2012
Сообщений: 5,557
03.09.2025, 14:22
Цитата Сообщение от power_factor Посмотреть сообщение
Требуется что-то вроде такого
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface IClassProperty { /* ... */ }
 
abstract class SomeClassBase
{
    public abstract IClassProperty classProperty { get; }
    
    protected static IClassProperty CreateClassProperty()
    {
        return new ClassProperty();
    }
    
    private class ClassProperty : IClassProperty { /* ... */ }
}
 
class SomeClass1 : SomeClassBase
{
    public override IClassProperty classProperty { get; } = SomeClassBase.CreateClassProperty();
}
 
class SomeClass2 : SomeClassBase
{
    public override IClassProperty classProperty { get; } = SomeClassBase.CreateClassProperty();
}
1
5 / 3 / 2
Регистрация: 27.04.2022
Сообщений: 60
05.09.2025, 19:11  [ТС]
Сделал вариант без интерфейса. Класс доступен вне объектов, но при попытке создания экземпляра даёт исключение.
Далее непонятно, каким образом это исключение нужно обработать, чтобы объект не был создан? Или он и так не будет создан?
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
    public class ClassProperty
    {
        public string Name { get; } = String.Empty;
        public ClassProperty(SomeClassBase someClass)
        {
            // Проверку на тип, передаваемый в конструктор, по идее делать не нужно
            if (someClass.IsExist == true) throw new Exception();
            Name = someClass.Description + " + its property.";
        }
    }
    
    public abstract class SomeClassBase
    {
        public bool IsExist { get; private set; } = false;
        public string Description { get; } = "It is an instance of SomeClass";
        public ClassProperty classProperty { get; }
        public SomeClassBase()
        {
            classProperty = new ClassProperty(this);
            IsExist = true;
        }
    }
    
    public class SomeClassOne : SomeClassBase { }
C#
1
2
3
4
5
6
7
private static void Main()
{
    var someClass = new SomeClassOne();
    Console.WriteLine(someClass.classProperty.Name); // проверка, что экземпляр ClassProperty создаётся
    var classProperty1 = new ClassProperty(someClass); // Exception
    var classProperty2 = new ClassProperty(new SomeClassOne()); // Exception
}
0
Эксперт .NET
 Аватар для Wolfdp
3785 / 1762 / 371
Регистрация: 15.06.2012
Сообщений: 6,535
Записей в блоге: 3
05.09.2025, 21:49
Цитата Сообщение от power_factor Посмотреть сообщение
Попробую объяснить свои рассуждения. Допустим, есть классы Воздух, Вода и Температура. Экземпляр класса Температура можно создать в экземпляре классов Воздух и Вода, но вот вне их нельзя, так как не может быть температуры "ничего".
Есть ощущение, что должны быть какие-то специальные паттерны агрегации/композиции для подобных задач.
гляньте это Запрет редактирования элементов извне класса

Добавлено через 3 минуты
Если нужно чтобы внешние сборки могли добавлять себя, то делаете internal метод в запечатанном классе, который вызываете из внешней сборки. Этот метод будет передавать интерфейс фабрики в класс, который должен получить доступ. Скорее всего нифига не поймёте с моего объяснения, но сейчас скинуть код не могу.
0
2393 / 1913 / 763
Регистрация: 27.07.2012
Сообщений: 5,557
05.09.2025, 22:50
Цитата Сообщение от power_factor Посмотреть сообщение
Или он и так не будет создан?
Если исключение возникает в конструкторе объекта, то он не создаётся.

Цитата Сообщение от power_factor Посмотреть сообщение
Сделал вариант без интерфейса.
Вы какую-то хрень нагородили. Вам показывали варианты, когда создать объект невозможно ещё на этапе компиляции. В вашем же случае "запрет" будет исполняться только уже в процессе работы. Вряд ли такое поведение можно назвать интуитивно понятным.
1
Эксперт .NET
 Аватар для Wolfdp
3785 / 1762 / 371
Регистрация: 15.06.2012
Сообщений: 6,535
Записей в блоге: 3
05.09.2025, 22:59
Цитата Сообщение от John Prick Посмотреть сообщение
Вы какую-то хрень нагородили. Вам показывали варианты, когда создать объект невозможно ещё на этапе компиляции. В вашем же случае "запрет" будет исполняться только уже в процессе работы. Вряд ли такое поведение можно назвать интуитивно понятным.
+1

Запрет должен быть "очевидным". Если я могу написать и скомпилить new MyClass(), но при этом он будет падать -- это не правильно.
0
5 / 3 / 2
Регистрация: 27.04.2022
Сообщений: 60
06.09.2025, 15:05  [ТС]
Цитата Сообщение от John Prick Посмотреть сообщение
Вы какую-то хрень нагородили.
На мой взгляд, в этом и заключается вся суть образовательного процесса: понимание работы инструментов через их применение и получение оценки от опытных людей
Цитата Сообщение от Wolfdp Посмотреть сообщение
Запрет должен быть "очевидным". Если я могу написать и скомпилить new MyClass(), но при этом он будет падать -- это не правильно.
Можно же сделать что-то вроде такого и тогда падать не должно:
C#
1
2
3
4
5
6
7
8
9
10
11
public ClassProperty(SomeClassBase someClass)
{
    try
    {
        if (someClass.IsExist == true) throw new Exception();
    }
    catch
    {
        Console.WriteLine("Создание невозможно. Объект не создан.");
    }            
}
0
Эксперт .NET
 Аватар для Wolfdp
3785 / 1762 / 371
Регистрация: 15.06.2012
Сообщений: 6,535
Записей в блоге: 3
06.09.2025, 17:12
Цитата Сообщение от power_factor Посмотреть сообщение
Можно же сделать что-то вроде такого и тогда падать не должно:
Вы совершенно не поняли суть претензии. Ваш код падает исключительно в рантайме. Т.е. сижу пишу скажем два часа сложную логику. Запускаю тест/отладку и возможно(!) увижу ошибку Exception. Нужно добиваться чтобы невалидный код даже не компилировался, не то что запускался.

Перечитайте тему что я указал выше. Там скидывали разные приёмы упаковки:
- вынос в интерфейс и работы с ним
- инжект конструктора через делагат нужным классам
- просто запаковка класса внутри другого
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,036
Записей в блоге: 2
07.09.2025, 00:26
Цитата Сообщение от power_factor Посмотреть сообщение
Пока мне видится описывать SomeClass и ClassProperty в отдельной .dll и делать internal ClassProperty (если это так работает вообще). Но ClassProperty может понадобиться и для совершенно других классов, описываемых в других сборках, про существование которых я ещё не знаю.
Если в отдельной сборке, то такой пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
namespace InternalCtor
{
    public class SomeClass
    {
        public ClassProperty Create() => new ClassProperty(this);
    }
    public class ClassProperty
    { 
        public SomeClass Parent { get; }
        internal ClassProperty(SomeClass parent) => Parent = parent;
    }
}
Добавлено через 2 минуты
Экземпляры ClassProperty можно создавать только методом экземпляра SomeClass.Create().
Но использовать эти экземпляры можно в каких угодно сборках.

Добавлено через 6 минут
Пример из .Net класс DataRow
1
2393 / 1913 / 763
Регистрация: 27.07.2012
Сообщений: 5,557
07.09.2025, 14:03
Цитата Сообщение от power_factor Посмотреть сообщение
Можно же сделать что-то вроде такого и тогда падать не должно:
Нет, здесь как раз объект будет создан. Т.е. своей цели вы не добились.
0
5 / 3 / 2
Регистрация: 27.04.2022
Сообщений: 60
07.09.2025, 15:20  [ТС]
Цитата Сообщение от John Prick Посмотреть сообщение
Нет, здесь как раз объект будет создан. Т.е. своей цели вы не добились.
Цитата Сообщение от John Prick Посмотреть сообщение
Если исключение возникает в конструкторе объекта, то он не создаётся.
Но ведь и исключение, и обработка всё ещё находятся в конструкторе.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,036
Записей в блоге: 2
07.09.2025, 15:29
Цитата Сообщение от power_factor Посмотреть сообщение
Но ведь и исключение, и обработка всё ещё находятся в конструкторе.
Конструктор срабатывает в рантайм.
Речь же о том, чтобы отлавливать такие ситуации ещё на стадии написания кода.

Конкретно в этом случае, экземпляр всё равно будет создан, но в консоль будет выведено сообщение об ошибке.
new всегда завершается созданием экземпляра или вылетом исключения.
Обработка такого исключения должна быть на уровне вызова new или выше.

В данном случае, корректный код для отбоя создания экземпляра должен быть такой:
C#
1
2
3
4
5
public ClassProperty(SomeClassBase someClass)
{
    if (someClass.IsExist == true)
        throw new Exception();
}

По месту использования
C#
1
2
3
4
5
6
7
8
9
10
    ClassProperty? propr;
    try
    {
        propr = new(someClass);
    }
    catch
    {
        propr = null;
        Console.WriteLine("Создание невозможно. Объект не создан.");
    }
1
5 / 3 / 2
Регистрация: 27.04.2022
Сообщений: 60
07.09.2025, 15:45  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Речь же о том, чтобы отлавливать такие ситуации ещё на стадии написания кода.
Это я уже усвоил) Просто интересно разобраться и в работе исключений тоже.
0
2393 / 1913 / 763
Регистрация: 27.07.2012
Сообщений: 5,557
07.09.2025, 16:01
Цитата Сообщение от power_factor Посмотреть сообщение
Но ведь и исключение, и обработка всё ещё находятся в конструкторе.
Нет. Объект не создаётся, если исключение покинет пределы конструктора. Если вы его в этом конструкторе перехватили, то поток выполнения успешно завершит конструктор и объект будет создан.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16115 / 11236 / 2887
Регистрация: 21.04.2018
Сообщений: 33,036
Записей в блоге: 2
07.09.2025, 16:07
Цитата Сообщение от Элд Хасп Посмотреть сообщение
new всегда завершается созданием экземпляра или вылетом исключения.
power_factor, не совсем корректно сформулировал.

Правильно так: new всегда завершается созданием экземпляра. Если при создании экземпляра возникнет исключение (это может быть при инициализации членов типа или экземпляра, при выполнении кода конструктора), new не завершится, а исключение, прервавшее его выполнение, будет передано выше.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.09.2025, 16:07
Помогаю со студенческими работами здесь

Создать класс Student (name и reting) со счётчиком экземпляров, с методами: конструктор, задание и изменения свойств
Доброго времени суток. Умы этого форума, прошу у вас помощи, а дело вот в чём... Нужно создать...

Задачи на использование классов и объектов, в которых данные описаны в качестве свойств
Круг на плоскости имеет координаты центра x0,y0 - вещественные свойства. Радиус круга r0 - также...

Клиент-сервер: Оповещение о событии других классов в зависимости от значения одного из полей
Есть пустыня. В пустыне есть область, где можно добывать полезные ископаемые. Вдалеке от этой...

Вывод в DataGridView полей некоторого экземпляра класса, в котором одно из полей является списком List
Здравствуйте, помогите плиз!!! Возникла потребность вывода в DataGridView полей некоторого...

Создание экземпляра класса наследующего значения из экземпляра родительского класса
Хочу создать новый экземпляр класса, который бы наследовал от другого экземпляра класса...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
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 - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru