(C#) Статическое поле для массива объектов, а не для класса. Возможно ли такое?
Предположим, что у меня есть класс RootBrother
и у него есть поле RootNum
типа int
. Создадим массив RootBrother[] rbs=new RootBrother[2000];
. Я хочу, чтобы у всего массива значение поля RootNum
было равно 19362363. Я не хочу, чтобы у каждого элемента массива было отдельное поле(лишнее место занимает(особенно когда массив имеет сотни тысяч элементов)), но и делать поле static
тоже не вариант (нужно, чтобы другие массивы или отдельные экземпляры того же класса могли иметь своё значение). Есть ли решение для подобных нужд без создания наследуемых классов?
Ответы (3 шт):
Так сделать нельзя. Но можно несколько по-другому:
using System;
class RootBrother {
public int Aprop;
public RootBrother(int init) { Aprop = init; }
}
class RootBrotherArray {
RootBrother[] rbs;
int rootnum;
public RootBrotherArray(int dimention, int init) {
rbs = new RootBrother[dimention];
for (int i = 0; i < dimention; rbs[i++] = new RootBrother(3));
rootnum = init;
}
public int RootNum { get { return rootnum; } }
public RootBrother this[int ind] {
get { return rbs[ind]; }
set { rbs[ind] = value; }
}
}
static class Program {
static void Main() {
var rbs = new RootBrotherArray(2000, 19362363);
Сonsole.WriteLine(rbs.RootNum);
Console.WriteLine(rbs[0].Aprop);
}
}
19362363
3
Я сделал класс RootBrotherArray, который ведёт себя, как массив, и имеет поле RootNum, которое содержит общую для всех элементов массива информацию. Aprop - это прото какое-то свойство для демонстрации.
Хотя, если таких общих свойств будет много, то можно провернуть такую штуку:
using System;
using System.Collections;
class RootBrotherArray : IEnumerable {
RootBrother[] rbs;
int rootnum, anotherrootnum;
public class RootBrother {
readonly RootBrotherArray parent;
public RootBrother(RootBrotherArray Parent) { parent = Parent; }
public int RootNum { get { return parent.rootnum; } }
public int AnotherRootNum { get { return parent.anotherrootnum; } }
}
public RootBrotherArray(int dimention, int init1, int init2) {
rbs = new RootBrother[dimention]; rootnum = init1; anotherrootnum = init2;
for (int i = 0; i < dimention; rbs[i++] = new RootBrother(this));
}
public RootBrother this[int ind] {
get { return rbs[ind]; } set { rbs[ind] = value; }
}
public int Length { get { return rbs.Length; } }
IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator) rbs.GetEnumerator(); }
}
static class Program {
static void Main() {
var rbs1 = new RootBrotherArray(10, 1983, 19362363);
Console.WriteLine(rbs1[0].RootNum);
var rbs2 = new RootBrotherArray(2, 753252, 1834534);
Console.WriteLine(rbs2.Length);
foreach (RootBrotherArray.RootBrother rbsi in rbs2) Console.WriteLine(rbsi.RootNum);
Console.WriteLine(rbs2[0].AnotherRootNum);
}
}
1983
2
753252
753252
1834534
Я добавил к классу RootBrotherArray перечислитель и свойство Length (другие необходимые недостающие члены можно реализовать также, как свойство Length). Класс RootBrother вложен в RootBrotherArray для того, чтобы иметь доступ и к приватным членам RootBrotherArray через поле parent, за счёт чего экземпляры RootBrother в одном массиве могут выдавать общие свойства, беря их из экземпляра массива (RootBrotherArray), элементами которого они являются.
Обратите внимание: если включить экземпляр RootBrother в другой массив, то он будет выдавать общие свойства, заданные при его создании.
Статическое поле/свойство для класса это данные, которые будут доступны только из самого класса, а не от экземпляра этого же класса. Хорошим примером является банковская система
. Независимо от количества клиентов и их внутренних параметров, для них всех будет одинаковый процент для кредитной ставки.
Если вы хотите, что бы каждый массив имел своё отдельное значение для RootNum
, вы можете вынести это всё в отдельный класс, что-то на подобии такого:
public sealed class RootObject
{
public int RootNum { get; }
public RootBrother[] Brothers { get; }
public RootObject(int rootNum, RootBrother[] rootBrothers)
{
RootNum = rootNum;
Brothers = rootBrothers
}
// методы для взаимодействия с Brothers
}
Работа с этим классом будет примерно следующим образом:
RootObject r1 = new RootObject(19362363, new RootBrother[2_000]);
RootObject r2 = new RootObject(100500, new RootBrother[10_000]);
Предложу другое решение благо их много.
class RootNumWrapper
{
public int Value { get; private set; }
public RootNumWrapper(int value)
{
Value = value;
}
}
class RootBrother
{
private RootNumWrapper _rootNumWrapper;
public RootBrother(RootNumWrapper rootNumWrapper)
{
_rootNumWrapper = rootNumWrapper;
}
public int GetRootNum()
{
return _rootNumWrapper.Value;
}
}
ну пример использования
class Program
{
static void Main()
{
// Создаем объект обертки с нужным значением
var rootNumWrapper = new RootNumWrapper(19362363);
// Инициализируем массив RootBrother
RootBrother[] rbs = new RootBrother[2000];
// Заполняем массив, передавая ссылку на один и тот же объект RootNumWrapper
for (int i = 0; i < rbs.Length; i++)
{
rbs[i] = new RootBrother(rootNumWrapper);
}
// Пример вывода
Console.WriteLine(rbs[0].GetRootNum()); // Выведет 19362363
}
}
RootNumWrapper — это класс, который инкапсулирует значение RootNum. Он хранит это значение и предоставляет доступ к нему через свойство Value.
RootBrother — класс, который принимает объект RootNumWrapper через конструктор и использует его для получения значения поля RootNum.
Мы создаем один экземпляр RootNumWrapper с нужным значением 19362363, а затем передаем его в каждый объект массива RootBrother. Все объекты массива будут ссылаться на один и тот же объект RootNumWrapper, что позволяет избежать дублирования данных.
Использование обертки для значения RootNum и передача этой обертки каждому элементу массива является хорошим решением. Это позволяет избежать дублирования данных, сохранить независимость объектов и соблюсти принципы SOLID и Clean Code.