Geeks With Blogs

News


Running with Code Like scissors, only more dangerous

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.

Posted on Thursday, January 17, 2008 9:40 PM | Back to top


Comments on this post: My C# 4.0 Wishlist, Part 3: The Return of Const-ness

# re: My C# 4.0 Wishlist, Part 3: The Return of Const-ness
Requesting Gravatar...
Wow! I thought I was the only one who missed C++ const modifiers on methods. I would like to have that kind of expressiveness back in C#. Thanks, Kevin
Left by W. Kevin Hazzard on Jan 31, 2008 12:54 PM

# re: My C# 4.0 Wishlist, Part 3: The Return of Const-ness
Requesting Gravatar...
Me too please !
Left by sfd on Oct 29, 2009 1:41 AM

Your comment:
 (will show your gravatar)


Copyright © Robert Paveza | Powered by: GeeksWithBlogs.net