Непонимание создания объекта в C # - PullRequest
4 голосов
/ 20 мая 2009

В этом посте есть пробел в моем понимании классов C # и почему они предпочтительнее статических функций.

Я пытаюсь получить список объектов. Каждый объект в списке представляет собой запись в таблице. Это было бы легко сделать в статической функции.

Используя класс, я смог сделать это следующим образом:

Процедура вызова:

ListOfBusinesses l = new ListOfBusinesses ();
List<Business> b = l.listBusinesses();

Занятия:

 public class Business
 {
    public string Bupk { get; set; }
    public string Bu_name { get; set; }

 }  

 public class ListOfBusinesses
 {
    public List<Business> listBusinesses()
    {

      List<Business> businesses = new List<Business>();
      businesses.Add(new Business("1", "Business Name 1"));
      businesses.Add(new Business("2", "Business Name 2"));

      return businesses;
    }
 }

Не могу я переписать класс так, чтобы это можно было сделать одной строкой:

ListOfBusinesses l = new ListOfBusinesses();

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

Я пытался:

public class ListOfBusinesses
{
    List<Business> businesses;

    public List<Business> ListOfBusinesses()
    {

      List<Business> businesses = new List<Business>();
      businesses.Add(new Business("1", "Business Name 1"));
      businesses.Add(new Business("2", "Business Name 2"));

      return businesses;
    }
}

Но получил ошибку компилятора "имена членов не могут совпадать с типом включения". Например, я пытался использовать конструктор, но что-то упустил.

Любая помощь могла бы просветить меня в области, которую я некоторое время неправильно понимал.

Майк Томас

Ответы [ 10 ]

9 голосов
/ 20 мая 2009

Я думаю, что вы смешиваете понятия статической функции, конструктора и фабричного метода.

Статическая функция

Определение

Это метод, который не имеет доступа (и не связан с) к экземпляру this класса.

Пример

public class BusinessHelper
{   
    public static List<Business> ListBusinesses()
    {

        List<Business> businesses = new List<Business>();
        businesses.Add(new Business("1", "Business Name 1"));
        businesses.Add(new Business("2", "Business Name 2"));

        return businesses;
    }
}

Использование

Вызвать статический метод с именем класса, а не экземпляром класса.

List<Business> businesses = BusinessHelper.ListBusinesses();

Конструктор : Это метод, который создает this экземпляр класса. Он не имеет возвращаемого значения и вызывается при создании экземпляра объекта.

Пример

public class BusinessList
{   
    public List<Business> TheList;

    public BusinessList()
    {    
        TheList = new List<Business>();
        TheList.Add(new Business("1", "Business Name 1"));
        TheList.Add(new Business("2", "Business Name 2"));   
    }
}

Использование

Создать новый экземпляр объекта.

BusinessList myBusinessList = new BusinessList();
businesses = myBusinessList.TheList;

Заводской метод

Определение

Это метод, который создает экземпляр объекта, каким-то образом создает его экземпляр и возвращает ссылку на него.

* * Пример 1 040 * +1041 *
public class BusinessList
{   
    public List<Business> TheList;

    public static BusinessList BusinessListWithTwoCompanies()
    {
        BusinessList instance = new BusinessList();

        businesses = new List<Business>();
        businesses.Add(new Business("1", "Business Name 1"));
        businesses.Add(new Business("2", "Business Name 2"));

        return instance;
    }
}

Использование

Вызовите фабричный метод вместо создания нового объекта.

BusinessList myBusinessList = BusinessList.BusinessListWithTwoCompanies();
businesses = myBusinessList.TheList;

Две вещи, на которые следует обратить внимание:

  1. Вы объявляете поле businesses, но приступаете к созданию другой переменной с именем businesses в вашем методе ListOfBusinesses() и возвращаете ее. С полем businesses ничего не случится. Будьте осторожны с переменной областью видимости.

  2. У вас не может быть члена (поля, свойства или метода) с тем же именем, что и у класса. Это зарезервировано для конструктора, который не имеет возвращаемого типа (см. Выше). Вот почему вы получаете ошибку компилятора.

5 голосов
/ 20 мая 2009

Конечно. Вместо инкапсуляции List<Business>, расширьте его. Тогда вам просто нужно добавить вещи в конструктор.

public class ListOfBusinesses : List<Business> {
    public ListOfBusinesses() : base() {
        Add(new Business("1", "Business Name 1"));
        Add(new Business("2", "Business Name 2"));
    }
}

Чтобы использовать это:

List<Business> l = new ListOfBusinesses();
2 голосов
/ 20 мая 2009

Реализация объекта в принципе одинакова для всех ОО-языков. Использование классов вместо статических функций обеспечивает гораздо большую гибкость и, в конечном итоге, меньшее количество кода, особенно при отслеживании многих похожих элементов.

Подумайте о книгах и библиотеках.

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

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

Я не буду публиковать какой-либо код, поскольку, пока я набираю этот код, многие другие опубликовали примеры кода для ваших бизнес-объектов.

1 голос
/ 20 мая 2009

Вы пытаетесь вернуть что-то отличное от класса в конструкторе

public class ListOfBusinesses
{
    ...

    public List<Business> ListOfBusinesses()
    {
        ...

Вы не можете указать тип возвращаемого значения в конструкторе, вам нужно:

public ListOfBusinesses()
{
    ...

Как сказал Майк Томас, вам следует вместо этого использовать фабрику, если вы этого хотите.

1 голос
/ 20 мая 2009

Ошибка вашего компилятора в том, что имя вашего класса - "ListOfBusications", а имя метода - "ListOfBususiness". Это было бы хорошо, если бы это был конструктор, но, поскольку у вас есть возвращаемый тип, C # думает, что вы подразумевали, что это был метод, а не конструктор.

Что касается получения списка предприятий, почему бы не создать такой класс:

public class BusinessService {
   public List<Business> GetBusinesses() {
       // Build and return your list of objects here.
   }
}

Затем использовать его:

BusinessService service = new BusinessService();
List<Business> businesses = service.GetBusinesses();
1 голос
/ 20 мая 2009

Вы ищете фабричный метод вместо конструктора.

0 голосов
/ 20 мая 2009

Если я не ошибаюсь, вы хотите получить доступ к БД и получить список объектов одним вызовом.

Прежде всего вам нужен класс DAO, который инкапсулирует доступ к базе данных и предоставляет метод List. Внутри DAO вы можете использовать NHibernate, Linq2XXX или что угодно (образец)

public class BusinessItem
{
    public string Code { get; set; }
    public string Description { get; set; }
}

public class BusinessItemsDAO
{
...
    public List<BusinessItem>   List()
    {
        // fake... should retrieve from db
        var list = new List<BusinessItem>();

        // returs the list
        return list;
    }
...
}

ваш код клиента может просто позвонить

var listOfBusinessItems = new BusinessItemsDAO().List();

возвращая IQueryable вместо List, может помочь, если у вас включен Linq.

0 голосов
/ 20 мая 2009

Как уже говорили люди - ваш синтаксис здесь не так. ListOfBusiness() является конструктором и не возвращает явно объект. Вместо этого он работает с новым экземпляром ListOfBusiness и должен позаботиться о любом необходимом создании.

Тем не менее, если ваш метод создания List<Business> прост, нет абсолютно никаких причин, по которым он должен быть частью статического метода. Вы даже можете определить метод расширения в List, который берет пустой список и заполняет его. Это называется шаблоном Factory, в котором метод или экземпляр объекта отвечает за создание новых экземпляров.

Если вы захотите подумать о расширении ListOfBusiness в созданный экземпляр класса, это если есть свойства или состояние, которые необходимо отслеживать. ЕСЛИ List<Business> меняется каждый раз, когда он вызывается, или если вам нужно место для добавления новых предприятий, класс ListOfBusiness может быть полезен для этого.

0 голосов
/ 20 мая 2009

Вообще говоря, вы не создадите свой класс ListOfBususiness, если только у ListOfBususiness нет некоторых свойств, которые недоступны в List . Простейшим способом обработки этого является статический метод класса Business, например:

public class Business
{
    //Business class methods/properties/fields

    static List<Business> GetList()
    {
        List<Business> businesses = new List<Business>();
        businesses.Add(new Business("1", "Business Name 1"));
        businesses.Add(new Business("2", "Business Name 2"));
        return businesses;
    }
}

Хотя это простой путь, конечный результат перехода по этому пути состоит в том, чтобы преобразовать этот метод из бизнес-класса в объектную фабрику, обычно предоставляемую через среду ORM, такую ​​как NHibernate или Castle Windsor.

0 голосов
/ 20 мая 2009

Проблема в том, что вы используете зарезервированное слово (новое) , используемое для вызова конструктора класса.

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

Если бы это было не так, тогда, если вы сделаете что-нибудь new MyObject ... как бы вы (или, если уж на то пошло, компилятор) узнали тип возвращаемого значения?

...