Name hiding in inheritance

The C++ name hiding rules for variables are well known by software developers. In contrast, name hiding in inheritance sometimes leads to issues although it follows the same rules. Such issues are therefore not a result of the rules but an effect due to different expectations in these different programming scenarios.

Name hiding rules for variables

Let’s start with the well-known rules for variables. The following example shows a typical scenario.

double x;
	
int main()
{
	int x;

	x = 5.5;	// conversion from double to int

	std::cout << x << std::endl;	// prints 5

	::x = 8.8;	// changes the global x

	std::cout << x << std::endl;	// prints 5
	
	return 0;
}

Within this example you see a double variable within the global scope and an integer variable within the local scope. As they have the same names, the local variable hides the global one, even if they have different types. If we want to access the double variable we must use the global namespace explicitly.

Name hiding rules in inheritance

At next, let us try the same name hiding within an inheritance scenario.

class Base
{
public:
	void Calc(double x) { std::cout << "Base calc was called" << std::endl; }
};

class Derived : public Base
{
public:
	void Calc(int x) { std::cout << "Derived calc was called" << std::endl; }
};

int main()
{
	Derived d;

	d.Calc(3.5);	// derived is called, conversion of double to int
	d.Calc(8);		// derived is called

	return 0;
}

Within this example we have a function with a double parameter in the base class and a function with an integer parameter in the derived class. The same name hiding rules like in the example before are still used. The local function of the derived class will hide the global function of the base class even if the function parameters are different.

Some developers are surprised by this behavior as they expect that the public functions of the base class will become functions of the derived class too and a function call with respect to the function parameters types can be executed. That’s a valid and comprehensible expectation because from a software architectural point of view public inheritance represents a “is-a” relationship.

From technical point of view the different kinds of inheritance just result in different visibilities of interfaces. Therefore, name hiding should be seen with respect to this technical point of view. So, the behavior of the example application is correct.

Make hidden names visible

Of course, there are many use cases where you want to keep the hidden names visible. For example, in public inheritance scenarios you normally want to have the interface visible and it should be a rare case to keep it hidden. As expected, this behavior was respected for C++. With the “using” statement the hidden names will become visible again. The following example shows the according modification of the derived class. This time the base class method is called if we pass a double parameter.

class Base
{
public:
	void Calc(double x) { std::cout << "Base calc was called" << std::endl; }
};

class Derived : public Base
{
public:
	using Base::Calc;	// make base class function name visible in derived class

	void Calc(int x) { std::cout << "Derived calc was called" << std::endl; }
};

int main()
{
	Derived d;

	d.Calc(3.5);	// base is called
	d.Calc(8);		// derived is called

	return 0;
}

Make specific hidden name visible

Within the previous example we have seen the “using” statement to make hidden names visible. As we already learned, names are independent of data types. Therefore, if we have different functions with the same name implemented in the base class, these functions will become visible. The following source code shows an according example. Furthermore, I have changed to private inheritance to show that the concept is independent of the inheritance kind.

class Base
{
public:
	void Calc(double x) { std::cout << "Base calc double was called" << std::endl; }

	void Calc(std::string x) { std::cout << "Base calc string was called" << std::endl; }
};

class Derived : private Base
{
public:
	using Base::Calc;	// make base class function name visible in derived class

	void Calc(int x) { std::cout << "Derived calc was called" << std::endl; }
};

int main()
{
	Derived d;

	d.Calc(3.5);	// base is called
	d.Calc(8);		// derived is called

	d.Calc("abc");

	return 0;
}

Based on a technical point of view the example looks fine. But from a software architectural point of view you may argue that it is bad design if we make the private interface public in derived class. And you are totally right. But sometimes such design decisions are made for several reasons. But in this case you want to keep the design fault as small as possible and make only one or a few of the available functions public. You can do this by using forward declaration instead of the “using” declaration. The following source code shows the adapted example.

class Base
{
public:
	void Calc(double x) { std::cout << "Base calc double was called" << std::endl; }

	void Calc(std::string x) { std::cout << "Base calc string was called" << std::endl; }
};

class Derived : private Base
{
public:
	void Calc(double x) { Base::Calc(x); };

	void Calc(int x) { std::cout << "Derived calc was called" << std::endl; }
};

int main()
{
	Derived d;

	d.Calc(3.5);	// base is called
	d.Calc(8);		// derived is called

	d.Calc("abc");	// compiler error

	return 0;
}

Summary

Names in derived classes hide names of base classes. This behavior is correct from a technical point of view. But in case of public inheritance it contradicts our expectations from a software architectural point of view. But we can easily make the hidden names visible again with the “using” declaration or with forward declarations.

Veröffentlicht unter C++ | Kommentar hinterlassen

Expression Bodied Members in C# 7

The concept of Expression Bodied Members (EBM) was introduced with C# 6 and as it becomes popular, many enhancements were added with C# 7. Within this article I want to give you the full picture of this feature so I explain the C# 6 and C# 7 EBM features.

With C# 6 the following EBM were introduced:

  • Expression bodied Methods
  • Expression bodied Properties

With C# 7 the following EBM were added:

  • Expression bodied Property Getter
  • Expression bodied Property Setter
  • Expression bodied Indexer
  • Expression bodied Operators Overloading
  • Expression bodied Constructor
  • Expression bodied Destructor (Finalizer)

Syntax

Member methods as well as property getters and property setters are sometimes implemented with a single instruction. In such cases the syntax overhead like brackets or getter and setter syntax is larger than the syntax for the real functionality. EBM allow to reduce the syntax overhead and therefore bring back the focus on the real functionality. This will increase the readability of the source code. For EBM a syntax is used which is already known from lambda expression: the “=>” sign. In contrast to lambda expressions you are limited to a single instruction. I think that’s a really good design decision because the EBM syntax only makes sense in such special cases. If your class members like constructor, property getters or methods contain several instructions, the bracket syntax used so far is more suitable. The instruction which belong together will be written into one block and therefore you can easily see that they belong together. But if you have one instruction only there is nothing which must be grouped. So, in this case it makes sense to leave out the block syntax and use a more lightweight style.

Examples

The following paragraphs show examples for each EBM type. As the examples are quite easily and self-explaining you will not find further descriptions or explanations. But at the end of the article you will find a summary and my personally thinking about the EBM feature.

Each example contains the same implementation twice: one time in EBM syntax and one time in standard block syntax. This allows an easy comparison of both implementation styles. But of course, if you want to compile the source code you must comment out one of the two implementations.

Expression bodied Methods

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  int result = myClass.Sum(3, 5);

  Console.WriteLine(result);
}

class MyClass
{
  // C# 6
  public int Sum(int a, int b) => a + b;

  // C# 5
  public int Sum(int a, int b)
  {
    return a + b;
  }
}

Expression bodied Properties

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  Console.WriteLine(myClass.Value);
}

class MyClass
{
  // C# 6
  public int Value => mValue;

  // C# 5
  public int Value
  {
    get { return mValue; }
  }

  private int mValue = 12;
}

Expression bodied Property Getter and Setter

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  myClass.Value = 42;
  Console.WriteLine(myClass.Value);
}

class MyClass
{
  // C# 7
  public int Value
  {
    get => mValue;
    set => mValue = value;
  }

  // C# 6
  public int Value
  {
    get { return mValue; }
    set { mValue = value; }
  }

  private int mValue = 12;
}

Expression bodied Indexer

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  Console.WriteLine(myClass[2]);
}

class MyClass
{
  // C# 7
  public int this[int index] => mValues[index];

  // C# 6
  public int this[int index]
  {
    get { return mValues[index]; }
  }

  private int[] mValues = new int[] { 11, 12, 13, 14 };
}

Expression bodied Operators Overloading

static void Main(string[] args)
{
  MyClass myClass = new MyClass();

  myClass.Value = 15;
  myClass++;

  Console.WriteLine(myClass.Value);
}

class MyClass
{
  // C# 7
  public static MyClass operator ++(MyClass myClass) => new MyClass() { Value = myClass.Value + 1 };

  // C# 6
  public static MyClass operator ++(MyClass myClass)
  {
    return new MyClass() { Value = myClass.Value + 1 };
  }

  public int Value { get; set; }
}

Expression bodied Constructor and Destructor (Finalizer)

static void Main(string[] args)
{
  MyClass myClass = new MyClass();
}

class MyClass
{
  // C# 7
  public MyClass() => Init();
  ~MyClass() => CleanUp();

  // C# 6
  public MyClass() { Init(); }
  ~MyClass() { CleanUp(); }

  private void Init() { }
  private void CleanUp() { }
}

Summary and Assessment

As you can see within the examples, the source code will become more readable as unnecessary syntax overhead is removed. From my point of view EBM is a quite nice feature. But of course, you should not overuse it. EBM should only be used if you have use a simple instruction. Furthermore, I don’t like to use EBM in ctor or finalizer in cases where you want to manage a single resource only. This feels a little bit inappropriate and most often you have more than one resource within a class. If you just want to call a single method in ctor or finalizer EBM is still fine.

Disadvantage of EBM

I think there is one minor disadvantage of EBM. The used ‘=>’ sign looks nearly like the ‘=’ sign. If you mix up these two signs you may write source code with another behavior than expected. The following example shows such an issue.

static void Main(string[] args)
{
  MyClass x;

  for (int i = 0; i  new MyLargeClass();
}

class MyLargeClass
{
  // ...
}

Both implementations look nearly the same but have a different behavior. One is an initializer the other one is a getter. So, in one case the value has a getter only and in the other case a getter and setter. Furthermore, one getter will always return the same object instance and the other one will always create a new object instance. Within the shown example this may result in huge performance differences depending on the kind of the returned object. Of course, this is a rare issue and it will not result in runtime errors. So, this theoretical disadvantage should not stop you from using EBM.

Veröffentlicht unter .NET, C# | Kommentar hinterlassen

C# Array indexer vs. List indexer

The C# CLR contains a lot of nice collection classes. They are optimized for their individual use case. But from a common perspective they all have the same behavior we expect from a collection.

But there is one exception from this rule: the array class. The array was added to the CLR from the very beginning and you can think of this class as a built-in generic. The array class has many differences compared to the other CLR containers. One major difference is the indexer. The indexer of the array returns the element by reference and not by value like all other collections.

This difference may have a huge importance if you choose the right collection for your use case. Furthermore, if an array indexer is used without respect to the fact that it returns a reference, it can result in undefined behavior.

The following example shows the difference between an array indexer and a list indexer.

static void Main(string[] args)
{
  var array = new[] { new MyStruct(42) };
  var list = new List { new MyStruct(42) };

  // array[0].mValue = 15;
  // list[0].mValue = 15;  // error CS1612: Cannot modify the return value because it is not a variable

  array[0].SetValue(15);
  list[0].SetValue(15);

  Console.WriteLine("Array value: " + array[0].mValue);   // output: 'Array value: 15'
  Console.WriteLine("List value: " + list[0].mValue);     // output: 'List value: 42'
}

public struct MyStruct
{
  public MyStruct(int x) { mValue = x; }

  public void SetValue(int x) { mValue = x; }

  public int mValue;
}

The example shows two important differences. If we try to set a member value, we will become an error message in case of the list collection. This is because the list indexer returns a copy of the object. As we don’t create a variable to store this copy, we are not able to set the member value. If we instead use a member function to set the value, the function call will be successful in both cases. But it has a different behavior. The array value will be changed but the list value will not. That’s because the array indexer returns a reference to the array element. The member function is called for this element. The list indexer returns a copy of the element. The member function is called on this temporary object. So, the origin list member is not changed at all.

The different behavior of array indexer and list indexer isn’t an error in the C# CLR. On the contrary, it offers advantages because you can choose the right collection type according to your needs. So, you should keep this special behavior of the array indexer in mind and use it if you have according use cases.

Veröffentlicht unter .NET, C# | 1 Kommentar

Object Instance Creation

Whenever you write an application in C++ you will create a lot of object instances. So, this is a base development task. C++ offers several ways to initialize variables. These are not just syntactical variations for the same task. The different initialization kinds may result in different behaviors. This rich variety of initialization kinds can result in some pitfalls, wrong expectations and programming errors.

Within this article I want to show the different object instance creation methods and explain their differences. To fully understand the examples of this article you should know the different types of constructors. You can get or refresh knowledge about constructors within this article.

Example Class

Within the examples of this article, a class “MyClass” is used. As we want to focus on the object instance creation, this class does not have any functionality. But it will provide several standard constructors and assignment operators. The ctor’s and operators just contain console outputs. This will help to see which ctor or operator is called. The following source code shows “MyClass”.

#include "stdafx.h"
#include 
#include 
#include 

class MyClass
{
public:
	MyClass();		// default ctor
	~MyClass();		// dtor

	MyClass(const int size);		// parameterized ctor

	MyClass(const MyClass& obj);		// copy ctor
	MyClass& operator=(const MyClass& obj);		// copy assignment operator

	MyClass(MyClass&& obj);		// move ctor
	MyClass& operator=(MyClass&& obj);		// move assignment operator

	MyClass(const std::initializer_list& list);	//initializer_list ctor
};

MyClass::MyClass() 
{
	std::cout << "default ctor" << std::endl;
}

MyClass::~MyClass()
{
}

MyClass::MyClass(const int size) 
{
	std::cout << "parameterized ctor" << std::endl;	
}

MyClass::MyClass(const MyClass& obj) 
{
	std::cout << "copy ctor" << std::endl;
}

MyClass& MyClass::operator=(const MyClass& obj)
{
	std::cout << "copy assignment operator" << std::endl;
	return *this;
}

MyClass::MyClass(MyClass&& obj)
{
	std::cout << "move ctor" << std::endl;
}

MyClass& MyClass::operator=(MyClass&& obj)
{
	std::cout << "move assignment operator" << std::endl;
	return *this;
}

MyClass::MyClass(const std::initializer_list& list) 
{
	std::cout << "initializer_list ctor" << std::endl;
}

Quiz

As a developer you already have implemented a huge number of object instantiations. Therefore, I want to start with a quiz. Following source code shows several ways to initialize MyClass. Please take a few minutes and think about these initializations. Try to answer following question for each line of code: Which ctor and/or assignment operator is called?

int main()
{
  MyClass test1;
  MyClass test2();
  MyClass test3{};
  <pre><code>MyClass test4(42);  
  MyClass test5{ 42 };

  MyClass test6(42.5);
  MyClass test7{ 42.5 };

  MyClass test8 = 42;
  MyClass test9 = 42.5;
  MyClass test10 = { 42 };
  MyClass test11 = { 42.5 };

  MyClass test12 = MyClass();
  MyClass test13 = MyClass(42);
  MyClass test14 = MyClass{ 42 };

  MyClass test15(test1);
  MyClass test16{ test1 };

  MyClass test17 = test1;
  MyClass test18 = { test1 };

  return 0;</code></pre>
}

MyClass test1

This is the simplest way to create an object instance. The default constructor will be called. Within the default constructor you should initialize all class members, otherwise they may contain garbage values.

MyClass test2()

Like before, this looks quite simple and we may expect that the default constructor is called. But not even close. This isn’t an object initialization at all. It is a function declaration. The function “test2” without parameters and a return value “MyClass” is declared. This C++ pitfall results in the redundant use of the parentheses. For backward compatibility the meaning of this code it still as in C++98 so it is still a function declaration. To bypass this pitfall, you should not use this syntax at all. Instead use the version seen above without parenthesis or use the braces syntax introduced with C++11 (as you can see in the next paragraph). But on the other hand, it is not a big issue because it will not result in errors. If you try to use the supposed object instance you will get according errors and if you not use the “test2” you get according compiler warnings too.

MyClass test3{}

This syntax was introduced with C++11. An object initialization with braces “{}” will call the default ctor. So, this syntax is equivalent to “MyClass test1”.

MyClass test4(42)

This will call the parameterized ctor and pass the “42” as parameter. The example class is a container type and therefore this object initialization will provide a container for 42 elements initialized with default value.

MyClass test5{ 42 }

If we use the braces syntax the values inside the braces will be converted to an initializer_list and therefore the initializer_list ctor is called. If we again think about the created container object we can say this time a container with one element was created and the element value was set to 42.

So “MyClass test4(42)” and “MyClass test5{ 42 }” will have different results but the syntax is nearly the same. This is a very important aspect and unfortunately a source for errors. Therefore, we should analyze this topic in more detail.

Furthermore, the braces syntax is still allowed even if we don’t have an initializer_list ctor. In this case the parameterized ctor is called according to the values given inside the braces.

In case a parameterized ctor and an initializer_list ctor exists the initializer_list ctor is prevered and will hide the parameterized ctor. This means if we get such a collision of two possible ctor’s the one with the initializer_list is prevered automatically and we don’t get any compiler warning. This may be a source for errors.

For example, we may use a container class “MyContainer”. This container class offers a parameterized ctor with two parameters: number of elements, initial value. We can create an object instance with “MyContainer x{10, 5}”. This will create a container with 10 elements all initialized with value 5. After a couple of time, the class MyContainer will be extended by the nice feature of an initializer_list ctor. But this new feature will change the behavior of the user code which uses the class. The existing initialization “MyContainer x{10, 5}” will now create a container with two elements of value 10 and 5. To fix this error we have to change the initialization and use parenthesis to call the hidden parameterized ctor: “MyContainer x(10,5)”.

This example shows the issues you may get with the initializer_list ctor. If you add this ctor to an existing class and if you have had parameterized ctor’s so far, they will get hidden and as a result you may break user code.

You will find an according example in the standard template library. The vector class offers an initializer_list ctor and it offers a hidden parameterized ctor with two parameters: number of elements, initial value.

MyClass test6(42.5)

The example class contains a parameterized ctor with an integer value as parameter. This parameterized ctor will be called even if the parameter does not match. An according value conversion is done. This narrowing conversion is allowed for some build in types but it may result in a loss of data and therefore an compiler warning will be shown.

MyClass test7{ 42.5 }

An object instance creation with braces will call the parameterized ctor too. But in contrast to the version above with parentheses syntax, narrowing conversions are not allowed. Therefore, in our example this object instantiation will result in an error.

MyClass test8 = 42

MyClass test9 = 42.5

MyClass test10 = { 42 }

MyClass test11 = { 42.5 }

These initializations are nearly the same as the ones explained above, with the syntactical difference that we use an assignment operator. But what’s the consequence of this different syntax? Will the assignment operator of MyClass be called?

The answer is simple: The use of the assignment operator is just a syntactical difference. These initializations are therefore equal to the ones explained above (see ’test4’ to ‘test7’).

Soo for test8 and test9 the parameterized ctor is called. Test10 will call the initializer_list ctor. Test11 will result in a compiler error as the narrowing conversion is not allowed.

MyClass test12 = MyClass()

MyClass test13 = MyClass(42)

MyClass test14 = MyClass{ 42 }

Now it becomes a little more difficult. What will happen in these cases? If we look at the different parts of the syntax, for example for the first case “MyClass test12 = MyClass()” we may think following: The “MyClass()” command creates an temporary object instance by calling the default ctor and “=“ will call the assignment operator and assign the temporary object to “test12” which was previously created due to the command “MyClass test12”. But this assumption is wrong. Unfortunately, I have heard it a few times, especially when people say you can optimize you code by eliminating the supposed temporary object and the call of several ctor’s and assignments.

So, what’s happening by using this kind of syntax? Nothing special! It has the same meaning as the syntax used for “test1”, “test4“ and “test5”. Therefore, for test12 the default ctor is called, for test13 the parameterized ctor is called and for test15 the initializer_list ctor is used. No temporary object is created and the assignment operator is never called.

In summary of the examples seen so far, we can say there is no difference between the following three initializations which will all call the parameterized ctor. Same is true for the default ctor and initializer_list ctor examples seen so far.

  • MyClass test4(42)
  • MyClass test8 = 42
  • MyClass test13 = MyClass(42)

These three spellings will create an instance of MyClass by calling the parameterized ctor. If you have read the article mentioned at the beginning you will answer back that there may be a theoretical difference. If we use explicit ctor’s the second syntax will no longer allowed. But that’s a restriction for explicit ctor’s only. In terms of common concepts, the three spellings will have the same result. But which one should be preferred? This depends on the coding guidelines of your company, your project team or your personal preferences. At the end of the article I will mention some coding guidelines.

MyClass test15(test1)

MyClass test16{ test1 }

These cases will call the copy ctor. As the given parameter is of type MyClass, the braces will not create an initializer_list.

MyClass test17 = test1

MyClass test18 = { test1 }

And again, the copy ctor will be called. As explained before, even if the syntax suggest that the assignment operator function is involved, it will never be called. So these initializations are nearly equal to the previous ones (test15 and test16) with the small difference that explicit ctor cannot be called.

Summary

As you can see there are many ways to initialize an object. These different initializations could have big differences in syntax but they have the same behavior. But unfortunately, there are some pitfalls to, like the initializer_list ctor which may hide a parameterized ctor. The braces syntax will offer uniform way to initialize objects. It should be used as preferred syntax as it can be used in nearly all cases. Following you will find some guidelines for object initializations but of course you may have your own coding guidelines or preferences.

Guidelines

Prefer object initialization with braces “{…}”, because it’s more consistent, more correct, can be used in nearly all cases and avoids old-style pitfalls at all.

In single-argument cases, especially on initialization of build in types, it is fine to omit the braces, for example “int i = 8;”.

In rare cases use parentheses “(…)” to explicitly call a ctor which is otherwise hidden by an initializer_list ctor.

When you design a class, avoid providing a ctor that ambiguously overloads with an initializer_list ctor. Users of your class should never need to use parentheses syntax to reach such a hidden ctor.

Veröffentlicht unter C++ | Kommentar hinterlassen

ctor types in C++

In C++ you will find several ways to initialize an object instance. For example, think about a class “MyClass” which can be constructed with a parameter. The object initialization can be done in several ways:

  • MyClass x{y};
  • MyClass x(y);
  • MyClass x = y;
  • MyClass x = {y};

But which one should be used? Do they all call the same constructor (ctor) or do these initializations lead to several results? Within the next two articles I want to think about these questions. The first article will show the several types of possible constructors and the second article will show the ways to initialize object instances.

Example object

For this article we want to create a simple class. An important task of a class is the resource management. So, the example class will contain a dynamically created memory resource which should be created by the different ctor types and released by the destructor (dtor).

Default ctor

Let’s start with the default ctor and the dtor. The default ctor does not have any parameters and it is used to initialize the class internal members.

<h1>include "stdafx.h"</h1>
<h1>include </h1>
class MyClass
{
public:
MyClass();      // default ctor
~MyClass();     // dtor

private:
int mSize;
int* mElements;
};

MyClass::MyClass()
: mSize(0)
, mElements(nullptr)
{
std::cout &lt;&lt; "default ctor" &lt;&lt; std::endl;
}

MyClass::~MyClass()
{
if (mElements)
{
delete[] mElements;
mElements = nullptr;
}
}

int main()
{
MyClass test1;      // default ctor
<pre><code>return 0;</code></pre>
}

Parameterized ctor

If we want to initialize the internal members with variable parameters, we can use a parameterized ctor. For example we can add a parameterized ctor to set the initial size of the data container.

<h1>include "stdafx.h"</h1>
<h1>include </h1>
class MyClass
{
public:
MyClass();      // default ctor
~MyClass();     // dtor
<pre><code>MyClass(const int size);        // parameterized ctor</code></pre>
private:
int mSize;
int* mElements;
};

MyClass::MyClass(const int size)
: mSize(size)
, mElements(mSize ? new int[mSize]() : nullptr)
{
std::cout &lt;&lt; "parameterized ctor" &lt;&lt; std::endl;
}

Copy ctor and copy assignment operator

Another often needed functionality is to create a copy of an existing object. This can be done by using a copy constructor. Furthermore, a copy assignment should be provided as a developer may use both ways to copy an object: copy it during creation or copy it by an assignment.

<h1>include "stdafx.h"</h1>
<h1>include </h1>
<h1>include </h1>
class MyClass
{
public:
MyClass();      // default ctor
~MyClass();     // dtor
<pre><code>MyClass(const int size);        // parameterized ctor

MyClass(const MyClass&amp; obj);        // copy ctor
MyClass&amp; operator=(const MyClass&amp; obj);     // copy assignment operator</code></pre>
private:
int mSize;
int* mElements;
};

MyClass::MyClass(const MyClass&amp; obj)
: mSize(obj.mSize)
, mElements(new int[obj.mSize])
{
std::cout &lt;&lt; "copy ctor" &lt;&lt; std::endl;
<pre><code>// create deep copy
std::copy(obj.mElements, obj.mElements + mSize, stdext::make_checked_array_iterator(mElements, mSize));</code></pre>
}

MyClass&amp; MyClass::operator=(const MyClass&amp; obj)
{
std::cout &lt;&lt; "copy assignment operator" &lt;&lt; std::endl;
<pre><code>// Self-assignment detection
if (this == &amp;obj)
{
    return *this;
}

// release resources
if (mElements)
{
    delete[] mElements;
    mElements = nullptr;
}

// create deep copy
mSize = obj.mSize;
mElements = mSize ? new int[mSize]() : nullptr;

std::copy(obj.mElements, obj.mElements + mSize, stdext::make_checked_array_iterator(mElements, mSize));

return *this;</code></pre>
}

As you can see, things become more difficult now. If we copy an object we must pay attention to several thins. At first, we should decide whether we want to create a deep or a flat copy. At next we must think about the resource management. This can be seen in the implementation of the copy assignment operator. It contains a self-assignment detection and prior to the resource creation we should releases the existing resources.

Move ctor and move assignment operator

The move ctor and operator should create a copy too. But in contrast to the copy operator we get an r-value as parameter and know that the source object is a temporary object only and will no longer be used. This will allow a more efficient resource management. As the source object in no longer used we can steal its resources instead of creating new ones.

<h1>include "stdafx.h"</h1>
<h1>include </h1>
<h1>include </h1>
class MyClass
{
public:
MyClass();      // default ctor
~MyClass();     // dtor
<pre><code>MyClass(const int size);        // parameterized ctor

MyClass(const MyClass&amp; obj);        // copy ctor
MyClass&amp; operator=(const MyClass&amp; obj);     // copy assignment operator

MyClass(MyClass&amp;&amp; obj);     // move ctor
MyClass&amp; operator=(MyClass&amp;&amp; obj);      // move assignment operator</code></pre>
private:
int mSize;
int* mElements;
};

MyClass::MyClass(MyClass&amp;&amp; obj)
{
std::cout &lt;&lt; "move ctor" &lt;&lt; std::endl;
<pre><code>// steal content of other object
mSize = obj.mSize;
mElements = obj.mElements;

// release content of other object
obj.mSize = 0;
obj.mElements = nullptr;</code></pre>
}

MyClass&amp; MyClass::operator=(MyClass&amp;&amp; obj)
{
std::cout &lt;&lt; "move assignment operator" &lt;&lt; std::endl;
<pre><code>// Self-assignment detection
if (this == &amp;obj)
{
    return *this;
}

// release resources
if (mElements)
{
    delete[] mElements;
    mElements = nullptr;
}

// steal content of other object
mSize = obj.mSize;
mElements = obj.mElements;

// release content of other object
obj.mSize = 0;
obj.mElements = nullptr;

return *this;</code></pre>
}

Again, we will add a self-assignment detection and release old resources. Furthermore, we have to reset the resources of the source object after we stole them. This will prevent the source object dtor to release these resources.

Copy & swap idiom

The copy ctor and the copy assignment operator as well as the move ctor and the move assignment operator contain some duplicate source code. There exists a common implementation technique which addresses this issue: the copy & swap idiom. This implementation technique comes with the advantage to remove this duplicate code but it will have some disadvantages too. Within this article I don’t want to explain the copy & swap idiom because it’s an own complex topic but you should keep in mind that this idiom is existing.

Initializer-list

Another important ctor type, especially for container like object, is a ctor with an initializer list. This will allow to pass an array of objects which is used to initialize the container class.

<h1>include "stdafx.h"</h1>
<h1>include </h1>
<h1>include </h1>
<h1>include </h1>
class MyClass
{
public:
MyClass();      // default ctor
~MyClass();     // dtor
<pre><code>MyClass(const int size);        // parameterized ctor

MyClass(const MyClass&amp; obj);        // copy ctor
MyClass&amp; operator=(const MyClass&amp; obj);     // copy assignment operator

MyClass(MyClass&amp;&amp; obj);     // move ctor
MyClass&amp; operator=(MyClass&amp;&amp; obj);      // move assignment operator

MyClass(const std::initializer_list&lt;int&gt;&amp; list);    //initializer_list ctor</code></pre>
private:
int mSize;
int* mElements;
};

MyClass::MyClass(const std::initializer_list&amp; list)
: mSize(list.size())
, mElements(mSize ? new int[mSize]() : nullptr)
{
std::cout &lt;&lt; "initializer_list ctor" &lt;&lt; std::endl;
<pre><code>if (list.size())
{   
    std::copy(list.begin(), list.end(), stdext::make_checked_array_iterator(mElements, mSize));
}</code></pre>
}

Use the different ctor types

The following source code contains an example console application which will create object instances. Depending on the given parameters the according ctor type is called.

int main()
{
MyClass test1;      // default ctor
<pre><code>MyClass test2(7);       // parameterized ctor

MyClass test3(test1);       // copy ctor
test3 = test1;                  // copy assignment operator

MyClass test4(std::move(test1));    // move ctor
test4 = std::move(test2);                   // move assignment operator

MyClass test5(7.1);     // parameterized ctor, warning: conversion from double to int

MyClass test6{ 1,2,3,4,5 };         //initializer_list ctor

return 0;</code></pre>
}

Implicit conversion ctor vs. explicit ctor

So far, we have implemented a couple of ctor’s for MyClass. With that ctor’s in mind do you think the following line of code will construct an object instance or will it show an error? If an object instance is created, which type of ctor is used?

MyClass test = 7;

This line of code will create a MyClass instance by calling the parameterized ctor. The parameterized ctor is also called a “conversion” ctor because it will allow implicit type conversion. In our case the MyClass instance is created based on an int value, so you can say the int value will implicit converted to an MyClass by calling the according parameterized ctor.

But maybe you don’t want to support such an implicit conversion. That may have several reasons. In my opinion such an implicit conversion looks a little bit strange and there are a lot of developers which don’t know the technical background about this line of code. Most will know that an object is created but some don’t know which ctor is used or whether it is a combination of ctor and assignment. This uncertainty and side effects on code changes may results in errors too. Therefore, you may prevent implicit conversion for some kinds of classes. In this case you have the possibility to declare the parameterized ctor as explicit. If you do so, the ctor cannot be used as implicit conversion ctor. The following source code shows an according example.

<h1>include "stdafx.h"</h1>
<h1>include </h1>
<h1>include </h1>
class MyClass1
{
public:
MyClass1() { std::cout &lt;&lt; "default ctor" &lt;&lt; std::endl; };
MyClass1(const int size) { std::cout &lt;&lt; "parameterized ctor" &lt;&lt; std::endl; };
MyClass1(const MyClass1&amp; obj) { std::cout &lt;&lt; "copy ctor" &lt;&lt; std::endl; };
};

class MyClass2
{
public:
explicit MyClass2() { std::cout &lt;&lt; "default ctor" &lt;&lt; std::endl; };
explicit MyClass2(const int size) { std::cout &lt;&lt; "parameterized ctor" &lt;&lt; std::endl; };
explicit MyClass2(const MyClass1&amp; obj) { std::cout &lt;&lt; "copy ctor" &lt;&lt; std::endl; };
};

int main()
{
MyClass1 test1 = 7;         // OK; calls parameterized ctor
MyClass1 test2 = 7.1;       // OK; calls parameterized ctor, warning: conversion from double to int
<pre><code>// MyClass2 test3 = 7;          // ERROR; implicit conversion from int to MyClass2 is not allowed
// MyClass2 test4 = 7.1;        // ERROR; implicit conversion from double to MyClass2 is not allowed
MyClass2 test6 = MyClass2(7);       // OK; calls parameterized ctor
MyClass2 test7 = MyClass2(7.1); // OK; calls parameterized ctor, warning: conversion from double to int

return 0;</code></pre>
}

MyClass2 offers an explicit ctor only. Therefore, the object instantiation cannot be done by using implicit conversion. Instead the parameterized ctor must be used explicitly. This may result in cleaner source code and may prevent errors.

Summary and outlook

Within this article we have seen the different types of constructors and got an introduction how to use them, for example to manage the resources needed by the object instance. Within the next article we will see the different ways to create an object and see which ctor is used in which situation.

Veröffentlicht unter C++ | Kommentar hinterlassen

Discard of return values and out parameters in C# 7

C# 7 allows to discard return values and out parameters. The underscore character is used as wildcard for these not required values.

The following source code shows an example of a function call where the caller wants to ignore the return value. Of course, in this case an assignment is not needed at all but it is possible by using the wildcard character.

static void Main(string[] args)
{
  DoSomething();
  _ = DoSomething();
}

private static int DoSomething()
{
  return 1;
}

Let’s stop for a moment and think about the example. This easy example may raise some questions:

  • Which of both syntax styles should be preferred?
  • Do we have any disadvantages if we use the short syntax?
  • Is it fine to ignore a return value at all or should we always assign and analyze return values?

If you read source code which contains the short syntax “DoSomething()” for a function call with ignored return value you will miss a very important fact: the function has a return value! Ignoring the return value may lead to errors. So, this code is a source of errors and the error is hidden as the reader of the code must explicitly have a look at the interface to see whether the function has a return value.

The syntax with the discard character explicitly contains the information that the function has a return value which is ignored. Of course, there is still an open question: why do we ignore the return? And as usual we should explain the “why” within a comment in the source code.

So, the second syntax is a little bit longer but it provides important information. The first syntax instead hides information and is a source for errors. It would be nice to get a compiler warning in such cases.

Discard ternary operator result

Let’s look at a second example where the compiler actually prevents ignoring of returns, the ternary operator. If you try to use the ternary operator without assignment of the return value, you will get a compiler error.

static void Main(string[] args)
{
  bool x = true;

  int y = (x == true) ? DoSomething() : DoSomethingOther(); //OK

  (x == true) ? DoSomething() : DoSomethingOther(); // compiler error

  _ = (x == true) ? DoSomething() : DoSomethingOther();   // OK
}

private static int DoSomething()
{
  return 1;
}

private static int DoSomethingOther()
{
  return 2;
}

Of course, the new discard wildcard can be used in this case too. But again, if we read such source code, we should ask why the return is ignored.

Discard out parameter

Beside the return value a function may have out parameters. As out parameters are nothing else as additional returns we can use the wildcard character for these parameters too.

static void Main(string[] args)
{
  DoSomething(out int _);
}

private static void DoSomething(out int x)
{
  x = 1;
}

Discard tuple elements

If the return value of a function is a tuple, we could discard the whole return value or parts of the tuple.

static void Main(string[] args)
{
  _ = DoSomething();
  (int result, _) = DoSomething();
}

private static (int result, int errorCode) DoSomething()
{
  return (5, 0);
}

Summary

It is possible to ignore return values or out parameter by using the discard parameter. But in my opinion, this is bad coding style. Ignoring these values means either the interface is strange as it contains unnecessary elements or the user of the interface mistakenly ignores important elements. Therefore, the discard parameter should be used in exceptional cases only and a clarifying comment is mandatory which explains why the interface element can be ignored.

Veröffentlicht unter .NET, C# | Kommentar hinterlassen

Tuples in C# 7 (ValueTuple)

Within this article I want to give a short overview over the new Tuple features in C# 7. So far, we already had a Tuple class in C#.  But with the new one some technical details have changed and some syntactical sugar was added. This new tuple syntax makes the source code more readable and perfectly integrates the technical advantages of tuples into the language. But of course, from a software design point of view tuples do have some common disadvantages too which are still present. Therefore, within this article I want to introduce the new tuple, the new syntax, show the technical background, mention the pros and cons and give hints when to use and when to avoid tuples.

Tuple syntax

Let’s start with a base example. We want to implement a function which may fail for several reasons. As we expect such failures the incomplete execution is a normal case which we want to evaluate and do according actions like repeat the method call. So, we don’t want to throw exceptions but return an according error code. Beside this error code the function returns a result. So, the function has two outputs: the function result and the error code as additional execution information. A common design pattern is to use an out parameter for the additional information.

static void Main(string[] args)
{
int errorCode;
var x = DoSomething(out errorCode);

if (errorCode == 0)
{
double y = x * 5;
}
}

private static double DoSomething(out int errorCode)
{
errorCode = 0;
return 4.2;
}


This common design pattern has one major disadvantage: it creates a complex data flow. The standard design of a function has a straight forward data flow: you have one or more input parameters which are passed on method call and you have one function result which will be assigned to a result variable. With output parameters you create a data flow which is way more complex. Would it be nice to return all outputs as function result to go back to the straight forward data flow? This can be done with tuples. The following source code shows the adapted example.

static void Main(string[] args)
{
var x = DoSomething();

if (x.Item1 == 0)
{
double y = x.Item2 * 5;
}
}

private static (double, int) DoSomething()
{
return (4.2, 0);
}

Within this source code the new tuple syntax is used so we don’t have to explicitly define a tuple instance. On function declaration we can define several return parameters and the compiler will create an according tuple. If we call the function we can assign the result to a variable and access the tuple parameters by the parameters “Item1” to “ItemX”.

This is a nice first step into the right direction. But it really bothers to call the tuple members by the generic properties with name “ItemX”. Of course, the new tuple syntax takes care of this aspect and allows to name the return values.

static void Main(string[] args)
{
var x = DoSomething();

if (x.errorCode == 0)
{
double y = x.result * 5;
}
}

private static (double result, int errorCode) DoSomething()
{
return (4.2, 0);
}

These named properties are a huge improvement for the code quality and will greatly increase the readability. But there is still one aspect which bothers me. On function declaration I don’t have to implement a tuple but just write down a list of returns. But on function call I must rethink and use a tuple now which holds the returns as properties. Would it be nice to use a value list on function call too? Of course, it would and fortunately this is supported by the new syntax.

static void Main(string[] args)
{
(double result, int errorCode) = DoSomething();

if (errorCode == 0)
{
double y = result * 5;
}
}

private static (double result, int errorCode) DoSomething()
{
return (4.2, 0);
}

This final version of the function implementation shows the big strength of the new syntax. We can implement a function with several return values and a straight forward data flow. Furthermore, the readability of the source code is highly increased as the technical details behind this concept are hidden and the source code is focused on functionality only.

Deconstruction of Tuples

As we have seen, on function call we can assign the several function return values to directly to according variables. This is possible because the returned tuple will be deconstructed and the tuple properties get assigned to the variables. Within a previous article you can find an introduction into the deconstruction feature which was also introduced with C#

As mentioned in the linked article, this deconstruction comes with a big issue. You can easily mix up return values if they have the same type. Within this example the compiler will show an according error if you switch the variables because they have different types. But with same types you may run into this issue. Later on, we want to think about the suitable use cases for tuples and we will evaluate this issue within the context of these use cases.

Discard of Tuple parameters

C# 7 allows to discard return values and out parameters. The underscore character is used as wildcard for these not required values.

The following source code shows how to use the discard character to ignore one of the return values.

static void Main(string[] args)
{
(double result, _) = DoSomething();

double y = result * 5;
}

private static (double result, int errorCode) DoSomething()
{
return (4.2, 0);
}

As mentioned within the linked article you should use this feature in rare cases only. To ignore a function result indicates that there is some software design issue within the function interface or in the is something wrong in the code which uses the interface.

When to use a tuple

As we have seen so far, tuples come with some pros and cons. So, we should not use them thoughtless. There are many situations were tuples are not the best choice. In my opinion there are only a few use cases were tuples should be used.

Sometimes you want to return more than one value from a method. This is a common use case but in a good interface design it should be a rare case too. Functions should do one thing only. Therefore, they have one result only. But sometimes additional to the result – what the function has done – it may be necessary to return execution information – how the method has been executed. These are for example error codes, performance measurement data or statistical data. This execution information contains very technical data about internal operations. With such an interface the component will become a gray box as it shows internal details and expect the right reactions of the user according this internal information.

As detail hiding is one of the base object-oriented concepts, such interfaces should be avoided. You want to have easy to use interfaces and your component should be a black box. In my opinion this is mandatory for high level interfaces.

On low level interfaces you may have a slightly different situation and explicitly want to get detail information about the component you use. You want to use it as gray box or even as white box. Furthermore, for performance reasons you may break some object-oriented rules or even mix object-oriented paradigms with functional and procedural paradigms. In such low-level interfaces, it is very common to have methods with several return values. But even in these cases I recommend having one result only – what the function has done – and one or more internal information about how it was done.

The options so far to implement several returns were less than optimal.

  • Out parameters: use is clunky and creates a method interface with a complicated data flow as in and out streams are mixed up
  • Custom-built transport type for every method: a lot of code overhead for a type which is used for one method only as temporarily object to group a few values
  • Anonymous types: high performance overhead and no static type checking
  • System.Tuple: best choice so far but with the need to allocate an object and with the disadvantage of code which needs comments to be easily readable (you must explain the tuple parameters)

With C# 7.0 we are now able to use the new tuple with the nice implementation syntax inspired by functional programming. It will make out parameters obsolete. This new tuple isn’t syntactical sugar only (compared with existing Tuple class) but also an improvement from technical side. We will analyze these technical details later.

You are now able to bundle up the different return parameters into one tuple element and use it as return value. You create a loose coupling between these values. Furthermore the coupling should exist in a small context only. The tuple is a temporary object with a short lifetime. A common pattern would be to construct, return and immediately deconstruct tuples.

In summary I would give following guidelines how to use tuples:

Methods in high level interfaces should return the result only. As they will hide internal details there is no need for additional output. Low level methods may return additional execution information. In this situation a tuple can be used. The return value and the execution information can be coupled within the tuple. This loose coupling exists for data transfer only as the tuple has a short lifetime and will be constructed, returned and immediately deconstructed.

As we have already seen at the beginning of the article, the biggest disadvantage of tuples is the risk to mix up parameters and create hard to find errors. If we use tuples in low level interfaces only, we can weaken this disadvantage. Low level components are gray or white boxes and the user has a high detail knowledge about the internals of such components. This reduces the risk to mix up parameters and it increases the chance to find such errors quickly. So, if we use tuples in these use cases only, the advantage of the good readability of the source code exceeds the disadvantage of the risk to mix up parameters.

Internals of tuple

As seen so far, the new tuple comes with a nice syntax. Of course, this is just syntactical sugar which helps to write clean code. So, we want to have a look behind the syntax and see what is done in the background. Let’s use the example with the named tuple elements and with deconstruction of the tuple.

static void Main(string[] args)
{
(double result, int errorCode) = DoSomething();

if (errorCode == 0)
{
double y = result * 5;
}
}

private static (double result, int errorCode) DoSomething()
{
return (4.2, 0);
}

If we disassemble the created application we will see the following code (disassembling with jetBrains dotPeek).

private static void Main(string[] args)
{
ValueTuple valueTuple = Program.DoSomething();
double num1 = valueTuple.Item1;
if (valueTuple.Item2 != 0)
return;
double num2 = num1 * 5.0;
}

[return: TupleElementNames(new string[] { "result", "errorCode" })]
private static ValueTuple DoSomething()
{
return new ValueTuple(4.2, 0);
}

This code shows some very important technical details. The used tuple is of the new type “ValueTuple” and not the longer exiting “Tuple”. “ValueTuple” is a struct, it is a value type and it has member values. “Tuple” instead is a class, a reference type and has properties. The “ValueTuple” is a lightweight type which comes with a better performance in nearly all cases. One exception is an assignment copy of a struct. As the whole content of the struct must be copied it is more expensive than a class copy which just copies the object reference. So, if you want to use a tuple with many elements and you have to copy this tuple very often then you might use a tuple class. Instead of the new ValueTuple struct. But as described in the previous paragraph, I would not recommend such a software design. Tuples should be used as temporary transport containers within a small context. If you must need a long living instance you should use an own data class instead of a tuple.

The second fact we see within the decompiled code is the naming mechanism of the tuple members. The names of the members are used within the IDE only. They are used to increase readability but they are not part of the resulting source code. So, you don’t have to fear expensive string comparisons if you use named tuple elements.

Tuple as function parameter

A tuple is a normal value type. So, you can pass a tuple as parameter to a function.

static void Main(string[] args)
{
DoSomething((4.2, 1));
}

private static void DoSomething(ValueTuple x)
{
double y = x.Item1 * x.Item2;
}

But should we use a tuple as function parameter just because it is possible from a technical point of view. I don’t think so. From software design point of view, I don’t see a use case for this feature.

Summary

The new tuple introduced with C#7, in combination with the new tuple syntax is a nice and powerful improvement of the C# language. It offers an efficient way to implement methods with several return values.

Veröffentlicht unter C# | Kommentar hinterlassen