C#: Как организовать разные действия у одного нестатического метода, задействуя минимум полиморфизма или не задействуя его вообще
— Один базовый класс без метода и класс-потомок с методом N, содержащим какое-либо поведение
— Экземпляров класса потомка более 40
— У каждого экземпляра класса-потомка метод N должен содержать разное поведение, определяемое непосредственно этим экземпляром
Грубо говоря:
class SomeClass : BaseClass
{
public Property1;
public Property2;
public Property3;
public MethodN (...)
{
//предположим, что тело метода определяется динамически
}
}
var instance1 = SomeClass();
var instance2 = SomeClass();
instance1.MethodN(); //выполнит одно действие
instance2.MethodN(); //выполнит другое
И таких instanceX более сорока
В то же время не обязательно, чтобы был всего один метод и всего один класс. В данном случае стоит вопрос "Как это вообще реализовать", а не "Как реализовать таким образом".
Мне нужно, чтобы при вызове метода из экземпляра в этом методе была та совокупность инструкций, которая соответствует данному экземпляру. Здесь бы подошли наследование и полиморфизм, но загвоздка в количестве таких предметов: их более сорока, соответственно, более сорока разных поведений метода.
В то же время я пытался выполнить подобное по-другому:
- Создать в классе множество методов (получилось грязно и нагруженно)
- Создать нестатическое текстовое поле, в которое записывается наименование одного из методов
- Посредством рефлексии получить из поля метод и вызвать его через делегат
Одно лишь использование рефлексии выдало значительные просадки в производительности, что было дополнено еще и тем, что операции по получению метода выполнялись довольно часто.
Ответы (2 шт):
В полиморфизме нет ничего плохого, перегружать метод в потомках - отличная практика. Много классов-потомков, у которых тело будет состоять из одной перегруженной функции - не проблема, на мой взгляд.
Но если вы упорно не хотите полиморфизма, можете просто конструктору класса передавать функцию (или делегат это называется что ли в C#), которую класс должен вызывать, и вызывать потом эту функцию в методе класса (если нужно, передавая функции некие параметры состояния класса).
Ещё вариант - сделать одну функцию со switch-ем внутри и при создании экземпляра задавать некий Enum, по которому этот switch будет переключаться при вызове этой функции. Это плохо с точки зрения ООП, но зато классов лишних не будет.
Определим класс следующим образом:
class BaseClass { }
class SomeClass : BaseClass
{
public int Property1 { get; set; }
public int Property2 { get; set; }
private readonly Func<int, int, int> _func;
public SomeClass(Func<int, int, int> func)
{
_func = func;
}
public int MethodN()
{
return _func(Property1, Property2);
}
}
При создании экземпляров передаём в конструктор делегат. Именно он будет реализовать поведение каждого конкретного экземпляра.
Например, someA будет складывать значения своих свойств, а someB - умножать.
var someA = new SomeClass((x, y) => x + y);
someA.Property1 = 2;
someA.Property2 = 3;
var someB = new SomeClass((x, y) => x * y);
someB.Property1 = 2;
someB.Property2 = 3;
Console.WriteLine(someA.MethodN()); // 5
Console.WriteLine(someB.MethodN()); // 6