Running with Code Like with scissors, only more dangerous

17Jan/080

My C# 4.0 Wishlist, Part 3: The Return of Const-ness

In C++, I can decorate member functions with the const modifier, which indicates that calling the member function will not modify the internal state of the object.  Here’s a sample class definition:

Test.h:

   1:  class CTest
   2:  {
   3:  private:
   4:      int m_nVal;
   5:   
   6:  public:
   7:      CTest(void);
   8:      ~CTest(void);
   9:      int GetValue() const;
  10:      void SetValue(int value);
  11:      int Add(int value) const;
  12:  };

Test.cx:

   1:  #include "Test.h"
   2:   
   3:  CTest::CTest(void)
   4:  {
   5:  }
   6:   
   7:  CTest::~CTest(void)
   8:  {
   9:  }
  10:   
  11:  int CTest::Add(int value) const
  12:  {
  13:      return value + m_nVal;
  14:  }
  15:   
  16:  int CTest::GetValue() const
  17:  {
  18:      return m_nVal;
  19:  }
  20:   
  21:  void CTest::SetValue(int value) 
  22:  {
  23:      m_nVal = value;
  24:  }

This example demonstrates wrapping an integer value, and shows how GetValue() and Add() can be const by not modifying any internal values.  Now, if I change the Add method to a void type, and add the value to the internal state, I get a compiler error.  Here’s the updated method:

   1:  void CTest::Add(int value) const
   2:  {
   3:      return SetValue(value + m_nVal);
   4:  }

Error:

error C2662: ‘CTest::SetValue’ : cannot convert ‘this’ pointer from ‘const CTest’ to ‘CTest &’

I get a similar error (about lvalue type casting) if I just set the value within the Add method.

So how should this apply in C#?  Realistically, I think I’d like it to just apply to member functions and properties.  There are a lot of ways to use const in C and C++ – it’s almost scary, actually (could you imagine using one parameter and having three const modifiers?).  In C#, I’d just like it to be part of the method contract:

   1:  public class Class1
   2:  {
   3:      private string m_firstName, m_lastName;
   4:      private int m_val;
   5:   
   6:      public int Value
   7:      {
   8:          get const
   9:          {
  10:              return m_val;
  11:          }
  12:          set
  13:          {
  14:              m_val = value;
  15:          }
  16:      }
  17:   
  18:      public string GetName() const
  19:      {
  20:          return string.Format("{0}, {1}", m_lastName, m_firstName);
  21:      }
  22:  }

In both of these examples, we can tell that the internal state of the object itself isn’t modified (note that the const modifier only applies to the get method of the Value property).  It provides the user of the class additional information, and it helps to enforce the contract on the side of the class author.

Implementation in the compiler: add a System.Runtime.CompilerServices.ConstMethodAttribute and apply it to the methods as marked.  Add a static code analysis rule that checks to see if a method could be marked as const, and if so, flag a warning.

I don’t know that there are compiler optimizations that can be made, but one way or another, I think that it’s a good method with which to give additional information about method implementations.  Sometimes we don’t want to call properties or methods if we know that it can cause side effects, because let’s be honest: the base class library’s documentation isn’t always 100% clear.  That’s why we need tools like .NET Reflector.  One more tool to help our code be self-documenting is one more good thing.

Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

ERROR: si-captcha.php plugin says GD image support not detected in PHP!

Contact your web host and ask them why GD image support is not enabled for PHP.

ERROR: si-captcha.php plugin says imagepng function not detected in PHP!

Contact your web host and ask them why imagepng function is not enabled for PHP.

No trackbacks yet.