У меня есть куча данных, которые я хочу создать в классе, и для каждой переменной я хочу, чтобы также был определен определенный набор методов. IE:
[TypeA] VarA
[TypeB] VarB
[TypeC] VarC
FA1() which is a function of VarA and VarB
FA2() which is a function of VarA and VarC
FB1() which is a function of VarB and VarA
FB2() which is a function of VarB and VarC
...
Поскольку будет большое количество переменных (и, следовательно, еще больше функций), я хочу разделить свой исходный код на управляемые куски. Поэтому я ищу автоматический способ убедиться, что все функции для каждой переменной созданы.
Я придумал 3 возможных метода организации моего кода, и я не слишком доволен каждым из них, и я ищу или советую, какой метод лучше (или даже если я пропустил совершенно другой метод реализации):
<сильный>1. Частичный класс
partial class Base
{
}
partial class Base
{
[TypeA] VarA;
FA1 { .. }; // function of VarA and VarB
FA2 { .. }; // function of VarA and VarC
}
partial class Base
{
[TypeB] VarB;
FB1 { .. }; // function of VarB and VarA
FB2 { .. }; // function of VarB and VarC
}
Плюсы:
- Простой
- Доступ к переменным возможен только из класса Base.
- Если есть две переменные одного типа, то функции для каждой переменной могут по-разному реализовывать свою собственную функцию.
Минусы:
- Невозможно автоматически гарантировать создание всех функций для каждой переменной
- Необходимо вручную убедиться, что между именами каждой функции нет конфликтов имен.
Обратите внимание, что Минусы могут быть решены каким-то генератором кода (может быть, пора изучить T4 ??)
<сильный>2. Внутренний класс
class Base
{
internal [ClassA] ObjA = new [ClassA]();
internal [ClassB] ObjB = new [ClassB]();
}
class [BaseClassA]
{
public [TypeA] VarA;
public virtual F1 { .. };
public virtual F2 { .. };
}
class [ClassA] : [BassClassA]
{
public override F1 { .. }; // function of VarA and ObjB.VarB
public override F2 { .. }; // function of VarA and ObjC.VarC
}
...
Плюсы:
- Иерархия классов обеспечивает создание всех функций и наличие доступа к переменным.
- Благодаря использованию виртуальных функций можно создавать конкретные реализации функций для конкретных экземпляров.
Минусы:
- Использование Internal означает, что данные видны везде в сборке.
<сильный>3. Статические данные
abstract class Data
{
static [TypeA] VarA;
static [TypeB] VarB;
...
}
abstract class [BaseClassA] : Data
{
public virtual F1 { .. };
public virtual F2 { .. };
}
class [ClassA] : [BassClassA]
{
public override F1 { .. }; // function of VarA and VarB
public override F2 { .. }; // function of VarA and VarC
}
class Base
{
[ClassA] ObjA = new [ClassA]();
[ClassB] ObjB = new [ClassB]();
}
Плюсы:
- Система гарантирует, что все подпрограммы созданы
- Данные не разлетаются по всей сборке
- Внутри каждой функции вы можете напрямую ссылаться на другие переменные в соответствии с решением «частичный класс».
Минусы:
- Использование static пахнет так, будто я заново изобрел глобальные данные.
Я хочу каким-то образом выбрать лучшие моменты каждого метода:
- Прямой способ доступа к переменным методов «Частичный класс» и «Статический»
- Локальные данные метода "Частичный класс"
- Автоматическое принудительное выполнение функций методов "Внутренний" и "Статический".
И я хочу избежать:
- Отсутствие принудительной генерации функции в «Частичном классе»
- Глобальный доступ к данным в методе «Внутренний»
- Переизобретение глобальных данных в «Статическом» методе
Если бы у меня были свои барабанщики, я бы сказал, что хочу каким-то образом применить интерфейс к экземпляру переменной, например:
[TypeA] VarA : IFunctions;
[TypeB] VarB : IFunctions;
И каким-то образом компилятор автоматически сгенерирует окончательные имена функций из имен интерфейсов и доступного имени.
Таким образом, люди могут предложить, какой из 3 методов они предпочли бы реализовать, или предложить любые другие методы, которые могут подойти.