C#. The relationship between classes of type uses (the class uses another class). Examples




The relationship between classes of type uses (the class uses another class). Examples

This topic is a continuation of the topic:


Contents


Search other websites:

1. The relationship between classes of type uses. Classification

When developing projects, it is important to determine how the class uses other classes. Different dependencies between classes appear implicitly in programming languages.

According to B. Straustrup (founder of the C++ language), between the two classes A, B, the following methods of use (uses) by class A of class B can be established:

  • 1. Class A uses the name of class B.
  • 2. Class A uses class B.
    • 2.1. Class A calls a member function of class B.
    • 2.2. Class A reads the data field of class B.
    • 2.3. Class A writes a class B data field.
  • 3. Class A creates an object of type B.
    • 3.1. Class A allocates memory for automatic objects of type B.
    • 3.2. Class A creates an object of type B using the new operator.
  • 4. Class A gets the size of class B.

 

2. Example. Class A uses the name of class B

 

using System;
using static System.Console;

namespace ConsoleApp1
{
  // Interaction between classes of type uses
  // Class A uses the name of class B

  // Class B - base class
  class B
  {
    // Hidden internal variable
    private int b = 25;

    // Virtual method
    public virtual void Print(B refB)
    {
      WriteLine("Method B.Print():");
      WriteLine("b = {0}", refB.b);
    }
  }

  // Class A - Derived from Class B
  class A : B
  {
    // Hidden internal variable
    private int a = 15;

    // In the parameter of the method of class A,
    // the name of class B is used as the base
    // for the implementation of polymorphism
    public override void Print(B refB)
    {
      WriteLine("Method A.Print():");
      base.Print(refB);
      WriteLine("a = {0}", a);
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Create an instance of class A
      A objA = new A();
      B objB = new B();

      // 2. Declare a reference to base class B
      B ref;

      // 3. Redirect the ref reference to the instance of class A
      ref = obj;

      // 4. Invoke the virtual method Print() using ref
      ref.Print(ref); // obj.Print(ref) is called

      // 5. Redirect the reference to base class B
      ref = obj;

      // 6. Invoke the virtual Print() method using the ref reference
      ref.Print(ref); // obj.Print(refB) is called
    }
  }
}

Program result

Method A.Print():
Method B.Print():
b = 25
a = 15
Method B.Print():
b = 25


 

3. Example. The relationship type uses. Class A uses class B

The example demonstrates several forms of interaction between classes that are of type uses.

using System;
using static System.Console;

namespace ConsoleApp1
{
  // Interaction between classes of type uses
  // Class A uses Class B

  class B
  {
    public const double Pi2 = 6.28;
    public double Pi = 3.14;

    static public void MethodB()
    {
      WriteLine("B.MethodB()");
    }
  }

  class A
  {
    public void MethodA()
    {
      // 1. Calling a member function of class B from class A
      B.MethodB();

      // 2. Accessing a class B data field from class A
      WriteLine(B.Pi2);

      // 3. Save the data field of class B
      B objB = new B(); // create an instance of class B
      objB.Pi = 3.141592; // save the data field
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Create an instance of class A
      A objA = new A();

      // 2. Invoke the method Method() of class A
      objA.MethodA();
    }
  }
}

Program result

B.MethodB()
6.28

 

4. Example. Class A dynamically creates an object of class B

This example is more relevant for the C++ language, since in this language a class object in a method can be created in two ways:

// C++. Method 1
B objB;

// C++. Method 2 - using the new operator
B* pB = new B();

In C#, all objects (instances) of a class are created dynamically using the new operator. This is due to the fact that classes are of reference type and not of value type. In the case of classes, reference types contain references to an instance of the class. The reference itself is placed on the stack, and the instance is placed in the heap. Therefore, to place an instance, you need to allocate memory dynamically.

The text of the demo program is as follows.

using System;
using static System.Console;

namespace ConsoleApp1
{
  // Interaction between classes of type uses
  // Class A dynamically creates an object of class B
  class B
  {
    // Internal field
    public int d;

    // Method Show()
    public void Show()
    {
      WriteLine("d = {0}", d);
    }
  }

  class A
  {
    // A method that dynamically creates an object of class B
    public void Demo()
    {
      WriteLine("Method A.Demo()");

      // 1. Create an instance of class B dynamically
      WriteLine("Creating instance objB.");
      B objB = new B();
      WriteLine("OK!");

      // 2. Fill a class B object with a value
      WriteLine("Fill with values objB.d.");
      objB.d = 330;
      WriteLine("OK!");
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Create an instance of class A
      A objA = new A();

      // 2. Invoke the Demo() method of class A
      objA.Demo();
    }
  }
}

Program result:

Method A.Demo()
Creating instance objB.
OK!
Fill with values objB.d.
OK!

 

5. Example. Class A gets the size of class B

The example demonstrates sizing an instance of a class using a serialization mechanism.

using System;
using static System.Console;

// It is necessary to use the Stream class capabilities
using System.IO;

// Required to use the BinaryFormatter class
using System.Runtime.Serialization.Formatters.Binary;

namespace ConsoleApp1
{
  // The original class B, which contains one field and one method

  // Before the class, it is indicated that the class will be stored in memory
  // (serialized class)
  [Serializable]
  class B
  {
    public double x;

    void ShowX()
    {
      WriteLine("x = {0}", x);
    }
  }

  // Class A, which contains a method
  // that determines the size of an instance of class B
  class A
  {
    // An instance of class B is created in the method
    // and its size is determined
    public void DemoSizeObjB()
    {
      // 1. Declare the internal variables
      long size = 0; // the size of class B instance
      B objB = new B(); // create an instance

      // 2. Using stream in binary memory
      // 2.1. Create a stream
      using (Stream s = new MemoryStream())
      {
        // 2.2. Create an instance of a binary
        //     serialization format
        BinaryFormatter bf = new BinaryFormatter();

        // 2.3. Write binary objB instance to memory
        bf.Serialize(s, objB);

        // 2.4. Determine the size of memory
        //     in which the instance was written
        size = s.Length;

        // 2.5. Print the size of the screen
        WriteLine("size = {0}", size);
      }
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Create an instance of class A
      A objA = new A();

      // 2. Invoke method DemoSizeObjB()
      objA.DemoSizeObjB();
    } 
  }
}

Program result

size = 129

 


Related topics