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 более сорока

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

Мне нужно, чтобы при вызове метода из экземпляра в этом методе была та совокупность инструкций, которая соответствует данному экземпляру. Здесь бы подошли наследование и полиморфизм, но загвоздка в количестве таких предметов: их более сорока, соответственно, более сорока разных поведений метода.

В то же время я пытался выполнить подобное по-другому:

  1. Создать в классе множество методов (получилось грязно и нагруженно)
  2. Создать нестатическое текстовое поле, в которое записывается наименование одного из методов
  3. Посредством рефлексии получить из поля метод и вызвать его через делегат

Одно лишь использование рефлексии выдало значительные просадки в производительности, что было дополнено еще и тем, что операции по получению метода выполнялись довольно часто.


Ответы (2 шт):

Автор решения: CrazyElf

В полиморфизме нет ничего плохого, перегружать метод в потомках - отличная практика. Много классов-потомков, у которых тело будет состоять из одной перегруженной функции - не проблема, на мой взгляд.

Но если вы упорно не хотите полиморфизма, можете просто конструктору класса передавать функцию (или делегат это называется что ли в C#), которую класс должен вызывать, и вызывать потом эту функцию в методе класса (если нужно, передавая функции некие параметры состояния класса).

Ещё вариант - сделать одну функцию со switch-ем внутри и при создании экземпляра задавать некий Enum, по которому этот switch будет переключаться при вызове этой функции. Это плохо с точки зрения ООП, но зато классов лишних не будет.

→ Ссылка
Автор решения: Alexander Petrov

Определим класс следующим образом:

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
→ Ссылка