Questions

  1. What is the difference between ref and out?

    • ref variables are “read-only”, their value cannot change inside a method.
    • ref is a keyword, out is not.
    • There isn’t any: they are both used to pass a reference to a method.
    • out variables may not be initialized going into the method, but have to receive a value inside the method.
    • There isn’t any: they are both used to pass a value to a method.
  2. What would be displayed by the following?

        static void AddR(ref int a, ref int b){
          int tmp = a;
          a = a + b;
          b = tmp - b;
        }
        
        int x = 4, y = 3;
        Console.WriteLine($"x is {x}, y is {y}.");
        AddR(ref x, ref y);
        Console.WriteLine($"x is {x}, y is {y}.");

    (Download this code)

    • “x is {x}, y is {y}.”, “x is {x}, y is {y}.”
    • “x is 4, y is 3.”, “x is 3, y is 4.”
    • “x is 4, y is 3.”, “x is 4, y is 3.”
    • “x is 4, y is 3.”, “x is 7, y is 1.”
    • This code would not compile.
  3. The following method would not compile. Why?

        static void Test1(int a, out int b){
          if (a > 0) { b = 12; }
        }

    (Download this code)

    • A method cannot be static and have void as a return type.
    • Any out parameter must have its value set in the body of the method.
    • The else is missing.
    • C# assumes that out parameters do not have a value.
    • The keyword out cannot be used in the header of a method.
    • An out parameter cannot be assigned a value.
  4. The following method would not compile. Why?

         static void Test2(int a, out int b){
                     if (b < 0) { b = a; }
                     else { b = 10;}
         }

    (Download this code)

    • A method cannot be static and have void as a return type.
    • Any out parameter must have its value set in the body of the method.
    • C# assumes that out parameters do not have a value.
    • The keyword out cannot be used in the header of a method.
    • An out parameter cannot be assigned a value.

Warm-up Exercises

  1. Consider the following code:

    using System;
     
    class Program
    {
      static void Main()
      {
        int x = 1;
        int y = 2;
        int z;
        char c = Foo(x, ref y, out z);
        char d = Foo(x, ref y, out z, '%');
      }
     
      static char Foo(
        int x,
        ref int y,
        out int z,
        char symb = '*'
      )
      {
        x++;
        y--;
        z = x + y;
        return symb;
      }
    }

    (Download this code)

    1. What are the values of x, y and z

      1. Before the Foo method is called?
      2. Inside the Foo method?
      3. After the Foo method executed?
    2. What is the value of c?

    3. What is the value of d?

    Solution

    1. We have the following:

      Whenxyz
      Before the Foo method is called12not set
      Inside the Foo method213
      After the Foo method102
    2. c holds '*',

    3. d holds '%'.

  • Consider the following method:

        static void NameChange(
          ref string nameP,
          string newnameP,
          out string oldnameP
        )
        {
          oldnameP = nameP;
          nameP = newnameP;
        }

    (Download this code) Assume given a string name variable containing a value. Write a short program (possibly declaring additional variables) that

    1. Asks the user their new name,
    2. Calls the NameChange method with appropriate arguments,
    3. Displays the new name and the old name.

    Solution

        string oldname;
        Console.WriteLine("Enter new name.");
        NameChange(ref name, Console.ReadLine(), out oldname);
        Console.WriteLine(
          $"New name: {name}\nOld name: {oldname}"
        );

    (Download this code)

  • Problems

    1. Write the AddLog method (header included) such that the following:

          string log;
          int x1 = 4,
          y1 = 3;
          int result = AddLog(x1, y1, out log);
          Console.WriteLine(log + "\n" + result);
          

      (Download this code) would display

      4 + 3 = 7.
      7

      Solution

          int AddLog(int xP1, int yP1, out string logP)
          {
            logP = xP1 + " + " + yP1 + " = " + (xP1 + yP1) + ".";
            return xP1 + yP1;
          }
          

      (Download this code)

    2. Write the AddReset method (header included) such that the following:

          int x2 = 2,
          y2 = 3,
          z2;
          AddReset(ref x2, ref y2, out z2);
          Console.WriteLine($"x2 = {x2}, y2 = {y2}, z2 = {z2}.");

      (Download this code) would display

      x2 = 0, y2 = 0, z2 = 5.

      Solution

          void AddReset(ref int xP2, ref int yP2, out int zP2)
          {
            zP2 = xP2 + yP2;
            xP2 = 0;
            yP2 = 0;
          }

      (Download this code)

    3. Consider the “regular” implementation of the Rectangle class:

      using System;
      class Rectangle
      {
          private int length;
          public int Length
          {
              get { return length; }
              set {
                  if (value < 0) {
                      throw new ArgumentNullException();
                  } 
                  else length = value; 
                  }
          }
       
          private int width;
          public int Width
          {
              get { return width; }
              set { if (value < 0) { throw new ArgumentNullException(); } else width = value; }
          }
       
          public Rectangle(int wP, int lP)
          {
              Width = wP;
              Length = lP;
          }
       
          public override string ToString()
          {
              return $"Width: {Width}\nLength: {Length}";
          }
      }

      And try to answer the following questions.

      Solution

      A possible solution to those questions is available.

      1. Write a Draw method that takes one optional char parameter and draw a rectangle of the calling object’s width and length using that character if provided, * otherwise. If your method is correctly implemented, then

        Rectangle r0 = new Rectangle(3, 2);
         
        r0.Draw();
        r0.Draw('-');

        should display

        ***
        ***
         
        ---
        ---

        Solution

        A possible solution is: public void Draw(char symb = '*') { string drawing = ""; for (int i = 0; i < Length; i++) { for (int j = 0; j < Width; j++) { drawing += symb; } drawing += "\n"; } Console.WriteLine(drawing); }

      2. Write a Copy method that does not take arguments, and return a copy of the calling object. If your method is correctly implemented, then

        Rectangle original = new Rectangle(5, 10);
        Rectangle copy = original.Copy();
        Console.WriteLine("Original:\n" + original + "\nCopy:\n"+ copy + "\n");
        copy.Length = 12;
        Console.WriteLine("\nOriginal:\n" + original + "\nCopy:\n" + copy + "\n");

        should display

        Original:
        Width: 5
        Length: 10
        Copy:
        Width: 5
        Length: 10
         
         
        Original:
        Width: 5
        Length: 10
        Copy:
        Width: 5
        Length: 12

        If the length of the original object changed after copy.Length = 12; was executed, then your method makes a shallow copy instead of a “deep” copy.

        Solution

        A possible solution is: public Rectangle Copy() { return new Rectangle(Width, Length); }

      3. Write an Equals method that return true if the calling object and the argument are both non-null rectangles with the same length and width, false otherwise. If your method is correctly implemented, then

        Rectangle r1 = new Rectangle(5, 10);
        Rectangle r2 = new Rectangle(5, 10);
        Rectangle r3 = null;
        Rectangle r4 = r1;
        Rectangle r5 = new Rectangle(10, 5);
         
        Console.WriteLine(
            "r1 and r2 identical: " + r1?.Equals(r2)
            + "\nr1 and r3 identical: " + r1?.Equals(r3)
            + "\nr3 and r1 identical: " + r3?.Equals(r1)
            + "\nr3 and r3 identical: " + r3?.Equals(r3)
            + "\nr1 and r4 identical: " + r1?.Equals(r4)
            + "\nr1 and r5 identical: " + r1?.Equals(r5)
            );

        should display

        r1 and r2 identical: True
        r1 and r3 identical: False
        r3 and r1 identical: 
        r3 and r3 identical: 
        r1 and r4 identical: True
        r1 and r5 identical: False

        Solution

        A possible solution is: public bool Equals(Rectangle rP) { if (rP == null) return false; return rP.Length == Length && rP.Width == Width; }