views:

718

answers:

12

This post goes to a gap in my understanding of C# classes and why they are preferable to static functions.

I am trying to get a List of objects. Each object in the list represents a record in a table. This would be easy to do in a static function.

Using a class, I've been able to do it as follows:

Calling routine:

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

The classes:

 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;
    }
 }

Couldn't I rewrite the class so that this could be done with one line:

ListOfBusinesses l = new ListOfBusinesses();

It seems to me like the ListofBusinesses class above is nothing but a static function wrapped in a class which has no properties and is only there for the sake of having a class.

I tried:

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;
    }
}

But received the compiler error "member names cannot be the same as there enclosing type". Eg, I tried to use a constructor, but am missing something.

Any help would enlighten me in an area I have misunderstood for some time.

Mike Thomas

+2  A: 

You are looking for a factory method instead of a constructor.

GregC
+5  A: 

Sure. Instead of encapsulating List<Business>, extend it. Then you just have to add things to it in the constructor.

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

To use it:

List<Business> l = new ListOfBusinesses();
Samir Talwar
Why would you extend the generic List<T> class? I don't see anything in the code that requires this at all.
Harper Shelby
It looked like Mike wanted a class that gave him a list with a default set of values already added. There are two solutions: use a factory, or extend the default list. I get the feeling that he wants to do more than add a couple of default values - perhaps add a couple methods or something - which is why he encapsulated it in the first place. I just think it would be easier to extend it.
Samir Talwar
A: 

Your compiler error is because your class name is "ListOfBusinesses" and the method name is also "ListOfBusinesses". This would be fine if it was a constructor, but since you have a return type on it, C# is thinking you meant it to be a method rather than a constructor.

As for getting your list of businesses, why not create a class like this:

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

Then to use it:

BusinessService service = new BusinessService();
List<Business> businesses = service.GetBusinesses();
Eric Petroelje
A: 

The problem is you're using a reserved word (new) used to invoke the constructor of the class.

The semantic of the constructor is to return an instance of the class which is being created and it follows the rule of having no return value and having the same name of the class.

If it wasn't that way, then, if you do any new MyObject ... how would you (or the compiler for that matter) be supposed to know the returning type?

Jorge Córdoba
+1  A: 

You're trying to return something different than the class in the constructor

public class ListOfBusinesses
{
    ...

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

You can't specify a return type in a constructor, you need:

public ListOfBusinesses()
{
    ...

As Mike Thomas said, you should use a factory instead if that's what you want.

GoodEnough
A: 

Generally speaking, you wouldn't create your ListOfBusinesses class, unless a ListOfBusinesses has some properties that aren't available in a List<Business>. The simplest way of handling this is a static method on the Business class, like so:

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;
    }
}

While this is the straightforward way, the end result of going down this road is to refactor this method out of the Business class and into an object factory, commonly provided through an ORM framework like NHibernate or Castle Windsor.

Harper Shelby
A: 

As people have said before - your syntax isn't right here. ListOfBusiness() is a constructor and doesn't explicitly return an object. It instead operates on a new instance of ListOfBusiness and should take care of any creation necessary.

That said - if your method to create the List is simple, there's absolutely no reason it should be part of a static method. You could even define an extension method on List that takes an empty list of that and populates it. This is called the Factory pattern, wherein a method or an instance of an object takes charge of creating new instances.

Where you would want to think about extending ListOfBusiness into an instantiated class is if there are properties or state that needs to be tracked. IF the List changes each time it is called, or if you need a place to add new Businesses, the ListOfBusiness class might be useful for that.

John Christensen
+5  A: 

I think you're mixing up the concepts of a static function, a constructor, and a factory method.

Static Function

Definition

This is a method which does not have access (and is not associated with) a this instance of a class.

Example

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;
    }
}

Usage

Call a static method with the class name, not an instance of the class.

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

Constructor: This is a method which creates the this instance of a class. It does not have a return value and is invoked when an object is instantiated.

Example

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"));   
    }
}

Usage

Create a new instance of the object.

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

Factory Method

Definition

This is a method that creates an instance of an object, instantiates it in some way, and returns a reference to it.

Example

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;
    }
}

Usage

Call the factory method instead of creating a new object.

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


Two things to additionally note:

  1. You declare a businesses field, but proceed to instantiate another variable called businesses in your ListOfBusinesses() method and return it. Nothing will happen to the businesses field. Be careful with variable scoping.

  2. You cannot have a member (field, property, or method) with the same name as the class. This is reserved for the constructor, which has no return type (see above). This is why you are getting the compiler error.

lc
A: 

Object instantiation is fundamentally the same for all OO languages. Use of classes rather than static functions allows for much more flexibility and ultimately less coding, especially when keeping track of many similar items.

Think of books and libraries.

If you have the book as an object class then you can instantiate it to create lots of books and store them in your library. Every book that you have instatiated is unique. If you have made no changes to it then each instantiated book appears to be a copy of the original (although at a low level each book has a unique serial number). It has the same cover, number of pages and content, BUT you can easily write your name in one copy thus making it different to the rest.

If you made the book a static then although you can't create individual copies, instead you are looking at the same book, but from different points of view. If you write your name in it then your name appears in every view of the book.

I wont post any code as whilst I've been typing this plenty of others have posted code samples for your business objects.

ChrisBD
A: 

If i'm not wrong you want to access a db and retrieve a list of objects with a single line call.

First of all you need a DAO class that encapsulates the db access and expose a List method. Inside the DAO you can use NHibernate, Linq2XXX or whatever you want (sample)

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;
    }
...
}

your client code could just call

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

returning an IQueryable instead a List could help if you are Linq enabled.

Andrea Balducci
A: 

Wow, many thanks for all of these answers. I had completely missed the fact that I had made a constructor which specified a return object. I got this to work as follows using the post from lc.

public ListOfBusinesses(String sSeek) { businesses = new List(); business.Add(new Business("1", "Business Name 1")); etc etc }

This seems pretty clean, but there is a lot more in these posts I want to go through.

Many thanks for your help. Mike Thomas

A: 

To go back to Samir's post - this was the one that worked for me in the end. What I am trying to do here is make a list with no default values. The list items will be added as a result of a SQL query. If the query has an empty result set, then no items should be added to the list. I only added the defaults as an example, but I see that it actually confused the question.

At any rate, I have a lot to do to understand what all is going on with Samir's solution.

Mike Thomas