#277 – Passing an Array to a Method

A variable that is the name of an array is just a reference to an instance of System.Array.  Since it is a reference type, when you pass an array to a method, you pass a copy of the reference.  This means that the method has the ability to read and write elements of the array.

Here’s a method that accepts an array as an input parameter.  The code demonstrates that you can read from and write to elements of the array.

        public static void DumpMovieInfo(MovieInfo[] movieList)
        {
            for (int i = 0; i < movieList.Length; i++)
            {
                // Read element of the array
                Console.WriteLine("{0} ({1}), {2}", movieList[i].Title, movieList[i].Year, movieList[i].Director);

                // Rewrite element
                movieList[i].Title = movieList[i].Title.ToUpper();
                movieList[i].Director = movieList[i].Director.ToUpper();
            }
        }

You would call the method as follows:

            MovieInfo[] movies = { new MovieInfo("The African Queen", 1951, "John Huston"),
                                   new MovieInfo("Casablanca", 1942, "Michael Curtiz"),
                                   new MovieInfo("The Godfather", 1972, "Francis Ford Coppola")};

            Movie.DumpMovieInfo(movies);

            Movie.DumpMovieInfo(movies);

#276 – Passing a struct by Reference

You can pass a struct by reference using the ref or out parameter modifiers.  Use ref when you want a method to read and write to the struct.  Use out for a struct that is meant to be an output parameter.

Assuming that you’ve defined the following struct:

    public struct MovieInfo
    {
        public string Title;
        public int Year;
        public string Director;
    }

You might pass an instance of MovieInfo by reference like this:

        public static void DisplayThenUpper(ref MovieInfo minfo)
        {
            Console.WriteLine("{0} ({1}), {2}", minfo.Title, minfo.Year, minfo.Director);

            minfo.Title = minfo.Title.ToUpper();
            minfo.Director = minfo.Director.ToUpper();
        }

After we call the method, the contents of the struct have been modified.

            MovieInfo minf = new MovieInfo();
            minf.Title = "Citizen Kane";
            minf.Year = 1941;
            minf.Director = "Orson Welles";

            Movie.DisplayThenUpper(ref minf);

            Console.WriteLine("{0}, {1}", minf.Title, minf.Director);

Output after the program has finished:

#275 – Passing a struct to a Method

You can pass an instance of a struct type to a method.  By default, the struct is passed by value, which means that a copy of the struct’s data is passed into the method.  This means that the method cannot change the contents of the original struct.

For example, assume you’ve defined the following struct:

    public struct MovieInfo
    {
        public string Title;
        public int Year;
        public string Director;
    }

A method that accepts an instance of this struct as a parameter might look like:

        public static void DisplayMovieInfo(MovieInfo minfo)
        {
            Console.WriteLine("{0} ({1}), dir by {2}", minfo.Title, minfo.Year, minfo.Director);
        }

And calling the method would look like this:

MovieInfo minf = new MovieInfo();
minf.Title = "Citizen Kane";
minf.Year = 1941;
minf.Director = "Orson Welles";

Movie.DisplayMovieInfo(minf);   // Passed by value -- copy of minf passed to method

#274 – Can’t Overload if Methods Differ Only by ref and out Modifiers

You can overload a method in a class, i.e. define two methods with the same name, if the methods have different lists of parameters.  The parameter lists must differ in the number of parameters or in their types.

For example, we can overload the Dog.Bark method if the parameters differ only in type:

        public void Bark(int numBarks)
        {
            // implementation here
        }

        public void Bark(short numBarks)
        {
            // implementation here
        }

We cannot overload a method if the parameters differ only in a ref vs out modifiers:

        public void FindDog(ref Dog aDog)
        {
            // implementation here
        }

        // Compiler will disallow this overload
        public void FindDog(out Dog aDog)
        {
            // implementation here
        }

#273 – Parameter Modifier Summary

Here’s a summary of the different parameter modifiers and how the behavior changes for each, when using them with value-typed and reference-typed variables.

  • No modifier – value types
    • Copy of value passed to method
    • Method can read value
  • No modifier – reference types
    • Reference to object passed to method
    • Method can read/write object contents
  • ref modifier – value types
    • Reference to variable passed to method
    • Method can read/write variable
  • ref modifier – reference types
    • Reference to object reference passed to method
    • Method can read/write object contents
    • Method can change reference to point to new object
  • out modifier – value types
    • Reference to variable passed to method
    • Method must write new value to variable
  • out modifier – reference types
    • Reference to object reference passed to method
    • Method must change reference to point to new object

#272 – Differences Between ref and out Parameters

Ref and out parameters in C# are implemented in the same way, in the compiled code.  In both cases, a parameter is passed by reference, giving the method called a chance to change the underlying value.

ref and out parameters different purposes:

  • ref parameters are for input/output – a value is passed into a method and a new value is passed out
  • out parameters are for output – a value is passed out of a method

The compiler enforces the following rules:

  • ref parameters
    • A value must be assigned to parameter before method is called
    • Parameter may be referenced inside method before being written to
    • Parameter may be written to before returning from method
  • out parameters
    • A value may be assigned before method is called (but cannot be used inside method)
    • Parameter may not be referenced inside method before being written to
    • Parameter must be written to before returning from method

#271 – Passing a Reference Type as an Output Parameter

You can pass a reference-typed variable to a method as an output parameter, using the out keyword.  This indicates that the parameter is an output method.  For a reference type, this means that the method is expected to change the reference to point to a different object.

        public static void FindBallPlayingDog(out Dog fav)
        {
            fav = null;
            foreach (Dog d in AllDogs)
            {
                if (d.Motto.Contains("ball"))
                    fav = d;
            }
        }

When calling the method, we need to include the out keyword as a parameter modifier:

            Dog kirby = new Dog("Kirby");
            kirby.Motto = "Love chasing balls";

            Dog jack = new Dog("Jack");
            jack.Motto = "Sneak away when possible";

            Dog fav = jack;

            Dog.FindBallPlayingDog(out fav);   // Fav is now Kirby

#270 – Passing a Reference Type by Reference

When you pass a reference type by value to a method, you pass in a reference to the object.  The method can change the object, but can’t change the reference.

        public static void AnnotateMotto(Dog d)
        {
            // Change the dog's motto
            d.Motto = d.Motto + " while panting";
        }

You can also pass a reference type by reference, which means that the method can change not only the contents of the object pointed to, but change the reference, causing it to refer to a different object.

        public static void FindNewFavorite(ref Dog fav)
        {
            fav.Motto = "No longer the favorite";

            foreach (Dog d in AllDogs)
            {
                if (d.Motto.Contains("ball"))
                    fav = d;
            }
        }

Below is an example of calling this method.

            Dog kirby = new Dog("Kirby");
            kirby.Motto = "Retrieve balls";

            Dog jack = new Dog("Jack");
            jack.Motto = "Growl at people";

            Dog myFav = jack;
            Dog.FindNewFavorite(ref myFav);

            Console.WriteLine(myFav.Name);   // Kirby

#269 – Use ref Modifier on Parameters that Are Input/Output

You can use the ref modifier on a parameter to signal that it should be passed by reference.  Instead of passing in a copy of the current value, a reference to the variable is passed into the method.  The method can read or change the current value.  Changes to ref parameters are seen by the calling code when the method returns.

The ref modifier should be used for input/output parameters, when you want to pass data into the method and also receive updated data when the method returns.

        public static bool DoubleBigNumber(ref int aNumber)
        {
            bool didIt = false;

            if (aNumber > 1000)
            {
                aNumber *= 2;
                didIt = true;
            }

            return didIt;
        }

When calling the method, you use the ref modifier for any ref parameters.

            int myNumber = 1200;
            bool didit = NumberHelper.DoubleBigNumber(ref myNumber);

            Console.WriteLine(myNumber);        // Value now 2400

#268 – You Must Set the Value of All out Parameters Before Returning from a Method

You can use out parameters as a way of returning multiple data values from a method to its caller.  Because the intention of an output parameter is to return data to the caller, you must assign some value to every parameter marked as out before you can return from a method.  The compiler will enforce this rule.

In the example below, we’ve failed to set a value for the barkPhrase output parameter.

        public void GetDogVitals(out string fullName, out int age, out string barkPhrase)
        {
            fullName = string.Format("{0}, {1}", Name, Title);
            age = Age;
            //barkPhrase = BarkPhrase;
        }

When we try to compile the code, we’ll get an error telling us that we must assign a value to the barkPhrase output parameter before control leaves the method.