Read-only ("const"-like) function parameters of C#
I think you may be looking for a solution involving two interfaces in which one inherits from the other:
public interface IReadableFoo
{
IMyValInterface MyVal { get; }
}
public interface IWritableFoo : IReadableFoo
{
IMyValInterface MyVal { set; }
}
public class Foo : IWritableFoo
{
private ConcreteMyVal _myVal;
public IMyValInterface MyVal
{
get { return _myVal; }
set { _myVal = value as ConcreteMyVal; }
}
}
Then you can declare methods whose parameter type “tells” whether it plans on changing the variable or not:
public void SomeFunction(IReadableFoo fooVar)
{
// Cannot modify fooVar, excellent!
}
public void SomeOtherFunction(IWritableFoo fooVar)
{
// Can modify fooVar, take care!
}
This mimics compile-time checks similar to constness in C++. As Eric Lippert correctly pointed out, this is not the same as immutability. But as a C++ programmer I think you know that.
By the way, you can achieve slightly better compile-time checking if you declare the type of the property in the class as ConcreteMyVal
and implement the interface properties separately:
public class Foo : IWritableFoo
{
private ConcreteMyVal _myVal;
public ConcreteMyVal MyVal
{
get { return _myVal; }
set { _myVal = value; }
}
public IMyValInterface IReadableFoo.MyVal { get { return MyVal; } }
public IMyValInterface IWritableFoo.MyVal
{
// (or use “(ConcreteMyVal)value” if you want it to throw
set { MyVal = value as ConcreteMyVal; }
}
}
This way, the setter can only throw when accessed through the interface, but not when accessed through the class.
First of all, you're correct: you cannot apply const or a similar keyword to parameters in C#.
However, you can use interfaces to do something along those lines. Interfaces are special in the sense, that it makes perfect sense to make an interface that only covers a specific part of a feature set. E.g. image a stack class, which implements both IPopable and IPushable. If you access the instance via the IPopable interface, you can only remove entries from the stack. If you access the instance via the IPushable interface, you can only add entries to the stack. You can use interfaces this way to get something similar to what you're asking for.
Consider Timwi's answer first. But as a second option, you could do this, making it more like the C CONST keyword.
Reference-type (object) parameters are IN parameters by default. But because they are references, their method side effects and property accesses are done to the object outside the method. The object doesn't have to be passed out. It has still been modified by the method.
However, a value-type (struct) parameter is also IN by default, and cannot have side effects or property modifications on the element that was passed in. Instead, it gets COPIED ON WRITE before going into the method. Any changes to it inside that method die when the method goes out of scope (the end of the method).
Do NOT change your classes to structs just to accommodate this need. It's a bad idea. But if they should be structs anyway, now you'll know.
BTW, half the programming community doesn't properly understand this concept but thinks they do (indeed, I've found inaccuracies on the matter of parameter direction in C# in several books). If you want to comment on the accuracy of my statements, please double check to make sure you know what you're talking about.