Должен ли класс С# генерировать экземпляры самого себя?

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

Я добавил статический метод в класс CallRate, который возвращает List<CallRate>. Хорошо ли для класса генерировать новые экземпляры самого себя, вызывая один из его собственных конструкторов? Это работает, мне просто интересно, правильно ли это делать.

List<CallRates> cr = CallRates.ProcessCallsFile(file);

Ответы

Ответ 1

Совершенно прекрасно получить объект от статического метода.

например.

Одна из библиотек точек сети делает то же самое, что и вы,

XmlReadrer reader = XmlReader.Create(filepathString);

Ответ 3

Я часто использую этот шаблон, когда мне нужно проверить правильность параметров. Категорически не рекомендуется бросать исключение из конструктора. Это не так плохо от метода factory, или вы можете выбрать null.

Ответ 4

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

Ответ 5

Это нормально. То, что вы только что создали, похоже на простой метод factory. У вас есть статический метод, который создает допустимый экземпляр типа. На самом деле ваш метод даже не должен быть статичным, и у вас все еще есть действующий код. Существует шаблон дизайна (Prototype), который создает новый действительный объект из существующего объекта. Подробнее см. http://www.dofactory.com/Patterns/PatternPrototype.aspx.

Ответ 6

Конечно, для простого разбора (или подобных) сценариев - я действительно предпочитаю factory method быть частью класса. Да - он прерывает SRP, но выполняет KISS - поэтому я называю это чистой победой. Для более крупных приложений или более сложных процедур синтаксического анализа - имеет смысл иметь внешний класс factory.

В вашем конкретном случае я бы предпочел метод, который использовался в IEnumerable <string> вместо имени файла - это все равно даст вам логику синтаксического анализа, но позволит легко тестировать единицы и "повторно использовать". Вызывающий может легко обернуть файл в IEnumerable.

Ответ 7

Factory методы часто являются хорошей конструкцией. Когда я пишу их в С#, я называю их "New", чтобы:

new MyClass()

становится

MyClass.New()

Тривиально он реализован следующим образом:

class MyClass
{
    public static MyClass New()
    {
        return new MyClass();
    }
}

В основном я делаю это, когда есть дополнительные условия о том, действительно ли создавать класс или просто возвращать null, или возвращать MyClass или что-то, полученное из него.

Ответ 8

Я иногда использую общедоступные статические методы как альтернативу перегрузке конструктора.

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

Ответ 9

Я поклонник статических методов, возвращающих экземпляры, как было предложено много раз, выше.

@Paul: не забудьте пометить комментарий выше, который вы найдете, это лучший ответ.

Ответ 10

Также как указать "генерировать новые экземпляры себя, вызывая один из своих собственных конструкторов"

Это не из конструктора, а из статического метода.

Ответ 11

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

    public class Car
    {
        public static Car RedExpensiveCar = new Car("Red", 250000);

        public Car()
        {

        }

        public Car(string color, int price)
        {
            Color = color;
            Price = price;
        }

        public string Color { get; set; }
        public int Price { get; set; }
    }

И с этим мне не нужно запоминать или писать параметры конструктора в моем коде.

Car car = Car.RedExpensiveCar;

Ответ 12

Это вполне приемлемо для этого. Когда я это делаю, я обычно делаю реальные конструкторы для класса private, так что он ясно, что единственный способ создания экземпляров - это статический метод.

Это очень полезно в тех случаях, когда "конструкция" может не всегда возвращать новый экземпляр. Например, вы можете захотеть вернуть ранее кэшированный объект.