Using Objects as Parameters in C#

Hands up, how many of you create monster functions and methods in your projects? And no, I’m not on about routines that are a million lines long, what did you think I meant? I’m actually talking about those functions that have signatures that could easily span over two lines if word wrap were turned on.

In Today’s Nuts & Bolts post, we look at why functions like this cause a problem, and what you can do to keep yourself from getting into these kinds of messes.

It’s not about any special thing that is specific to .NET but a general programming technique that makes your code easier to read, and begins to help you understand IoC (Inversion of Control)

Starting with the Problem

We’ve all seen them, those functions & methods that seem to go on forever:

public Class1()
{
  public myMethod(int age, string name, string surname, int yearBorn, int weight, float xlocation, float ylocation ......)
  {
  }
}

You can see that even my example is hard to read, and it’s not even in a full blown project with many other lines of code. Imagine, trying to navigate a source file that had masses and masses of function prototypes like this; I think finding a needle in a haystack would be much easier.

Why is This Bad?

Well we’ve already seen one reason why coding like this is bad; readability.  You might be okay with it when you’re writing this code, but what happens when you come back six months later? Imagine you’re the maintenance programmer who has to take over looking after this thing, and answering inbound support calls from customers out in the field using the software. These are just a couple of reasons to consider. There are many other reasons too.

What if during development your specs get changed, and you suddenly find that you need to add a parameter to pass in a value of how much food is eaten in a month. What about if you need to rename a parameter?

Going one step further, what about optional parameters? You know the ones where you can add a default value:

public myMethod(int age = 20 ......)
{
}

Imagine if you had to update that “20” to a “40” in all instances.

Very quickly this becomes something that’s very likely going to lead to mistakes being made in your project, and if you’re under any doubt about how easy it is to miss a parameter like that amongst masses of other code, take some advice from me, it’s stupidly easy.

I like many professional developers have been there and made these mistakes, and it’s no fun spending a Sunday afternoon trying to hunt down something you just can’t quite put your finger on.

How do You Solve This?

As it happens, it is quite easy to solve this. Instead of adding all your parameters in one go, use an object.

Now before we go any further, notice I’m using the term ‘Object’ here.  To me this will generally mean a class, some people however prefer to use structs, some prefer generic objects, it really doesn’t matter what you use, the principle is still the same, and I have no desire to get into a religious war over which type is best.

One thing I will say is each type has its advantages and its disadvantages, and if any of you have ever read my posts in Lidnug, then you’ll know already that I’m a firm believer in looking at all your options and using the correct tool for the job.

Moving on.

Let’s take our example above:

public myMethod(int age, string name, string surname, int yearBorn, int weight, float xlocation, float ylocation ......)

We can see that we have at least seven items of data we’re using, so let’s flesh this out into a class.

public class myMethodParams
{
  public int age { get; set;}
  public string name { get; set;}
  public string surname { get; set;}
  public int yearBorn { get; set;}
  public int weight { get; set;}
  public float xlocation { get; set;}
  public float ylocation { get; set;}
}

And then change our function signature:

public void myFunction(myMethodParams theParams)
{
}

Immediately it looks much more readable.

But now we have other benefits too.

Because a class is being used, you can add methods that can act just like parameters, and in fact this is one of the underlying concepts of object orientated programming, making objects self aware and expose only what they need to.

Encapsulation is a very powerful thing when used correctly, to ‘myMethod’ all it sees is what it needs to see, nothing more.

What about Defaults? Well, you can easily add an extra field, and then some code to initialize it to a known value:

public class myMethodParams
{
  public int age { get; set; }
  public string name { get; set; }
  public string surname { get; set; }
  public int yearBorn { get; set; }
  public int weight { get; set; }
  public float xlocation { get; set; }
  public float ylocation { get; set; }
 
  public myMethodParams()
  {
    age = 20;
  }
}

If you never set ‘age’ to a value, you can guarantee that it’ll be set to ’20’ and not have to worry about it.

Is This Just a Quick Tutorial on OOP?

If you’ve done any formal programming language training in the past ten years then this stuff will be (or should be) second nature to you. If you’ve not, then this might be new to you. Regardless, having a refresher never really hurts anyone.

Ask yourself this question though:

How often do you pass full classes/objects as parameters to regular methods?

I’m willing to bet not very often. In fact I’ll even go so far as to say that most of you probably do something like this most of the time:

public class HomeController : Controller
{
  public HomeController(myDataObject theObject)
  {
  }
 
  public ActionResult Index()
  {
    return View();
  }
}

And leave it at that.

Well what your actually practicing here is ‘IoC’, which means ‘Inversion of control’. Essentially what you’re doing is your passing an object that’s responsible for its own state, has its own processing methods and likely quite a chunk of other functionality.

Why ‘Inversion’?

Well it’s because you’re giving the data object the control of its lifetime within the ‘Controller class’ it’s used in above, rather than the traditional way of having the controller class ‘new’ a copy of the data object, and control it.

You’re taking control away from the class that’s using the data object, and inverting that control, so that the data object is in charge.

In Summary

The point I’m trying to make here though, is why only restrict yourselves to the scenario above?

ASP.NET MVC enforces this paradigm by default, but there’s absolutely no reason why you can’t make your own code/projects easier to manage and easier to read by adopting similar methods.

If you have any ideas for posts for this series, please reach out to me on twitter ‘@shawty_ds’ or come and find me in the Linked .NET users group (Lidnug) on the Linked-In social network. Until next time, code happy.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read