0

In C++, you can pass into a function an object that is const. This forces the code to treat that object as 'read only' (ignoring the fact that you can strip constness away using casts). I'm trying to do the same with C#. I have an interface that the user will implement. One of the methods will be given an object as a parameter. How do I make the object 'const' in the scope of the method and mutable otherwise.

Solution: interfaces. I make an interface where the only action available on a property, is 'get'.

public interface IVal { ... }


public interface IFoo
{
    IVal Val { get; }
}

public class Foo : IFoo
{
    public IVal Val { get; }
}

I pass by interface and everything is amazing. However, in my concrete class, I would like to have a 'set' available. It would allow me to set a concrete class Value. How would my concrete class look like?

I was thinking of using the 'internal' keyword. I read that it exposes the method/property to code within your own assembly. Is this my answer?

EDIT: To illustrate this better, I added a setter that would automatically cast for me. However, for each property, this is a lot of repetative code:

private Val _val;
public IVal Val
{
    get { return this._val; }
    set { this._val = value as Val; }
}
MarkP
  • 4,168
  • 10
  • 43
  • 84
  • Having a setter like that is probably a bad idea. If I try to set it to something that is not `Val`, it will silently set it to `null`. That's not what most people would expect. You should probably decide whether you want `Val` or `IVal` and stick to it. – svick Nov 23 '11 at 02:09

2 Answers2

3

You can just add the set and it will work fine:

public IValue Value { get; set; }

Like this, you can set the value if you have Foo, but not if you have IFoo. Similar to the C++ case, if you have IFoo, you can cast to Foo (as long as the object actually is Foo) and then use the setter.

Another option is to make the setter protected or private:

public IValue Value { get; private set; }

This allows you to make sure that only code in this class (or inherited classed in the case of protected) can set the property.

Regarding internal: yes, it exposes the member only to code in the same assembly (and friend assemblies). But this is not used very often. What is used (and useful) are internal types, which is even the default, if you don't specify that that class is public.

This could help you with your problem. If you make Foo internal, a method in other assembly that has IFoo won't be able to set the property, even with casting.

Of course, the code could always use reflection to set the property. But you shouldn't worry about that most of the time.

svick
  • 236,525
  • 50
  • 385
  • 514
  • If I was to set a value to this, I would have to cast to the interface. this.Value = new Value(); causes an error, forcing me to do a cast each time I assign. This is my biggest gripe, is there a better way of doing this? – MarkP Nov 23 '11 at 02:00
  • I get the error 'Cannot implicitly convert from Val to IVal...' – MarkP Nov 23 '11 at 02:04
1

You can do similiar thing

public class ReadonlyTestClass {
 private readonly object _name;
 public ReadonlyTestClass(object name) {
   _name = name;
 }
 public object Name {get { return _name; }}
}

Or

public class ReadonlyTestClass {
 public ReadonlyTestClass(object name) {
   this.Name = name;
 }
 public object Name {get; private set;}
}
Peter PAD
  • 2,252
  • 1
  • 17
  • 20
  • I would like the 'set' be available outside the class to my other classes. I would like it to remain hidden to another person's classes. – MarkP Nov 23 '11 at 02:01