This is a read-only archive!

C# annoyance of the day

Those annoyances just keep coming, right? Consider this Ruby code:

class Parent
  def foo
    puts @var
  end
end

class Child1 < Parent
  def initialize
    @var = 'bar'
  end
end

class Child2 < Parent
  def initialize
    @var = 'baz'
  end
end

Child1.new.foo
Child2.new.foo

This works fine. Note that the Parent class itself doesn't have a @var instance variable. If you tried to instantiate a Parent and call Parent#foo, it would not work properly (unless getting a nil is your idea of proper). Ideally, Parent should be an "abstract" class like C# or Java provide; it's not really a complete class definition, it's more of a framework for children. Though it could be a Module instead of a Class, I made it a Class because I want to compare it to C# which doens't have Modules.

Assuming the programmer knows enough not to try to call Parent#foo, the above works fine in all cases. That's because Ruby has a "What I don't know won't hurt me" philosophy. Parent#foo has no idea whether a @var instance variable exists or not, and it doesn't care. The Parent class could be re-opened later, after all, and a @var added. Or as in this case, a child could make the instance variable. Parent#foo crosses that bridge when it comes to it, and crosses its fingers and hopes there's a @var waiting for it by the time you call Parent#foo.

In C#, I'm pretty sure you can't do the above. In a parent class, if you try to play with an instance variable, that instance variable must exist in the parent class. Even if the parent class is abstract, there must be what amounts to not much more than a placeholder in the parent class for every instance variable that's accessed in a the parent class's methods. Even if you know to be REALLY CAREFUL to make sure all your children define a "var" so that the parent's method always has one to use, and even if you never directly instantiate the parent class (if it's abstract, you can't instantiate it anyways) the compiler isn't going to trust you to do the right thing. If the parent uses a "var', the parent must have a "var" spelled out in the code.

Maybe there's some way to make this work in C#, maybe I don't know enough about the language. But the solutions I found are:

  1. Make a "var" instance variable in the parent class, and initialize it to some garbage value. Then make sure to change that value in the child classes. I hate doing this because the instance variable SHOULD NOT EXIST in the parent class. It should never be used. If I don't create it in my child classes, I don't want my child classes to accidentally use the garbage value of that instance variable in the parent class.

  2. Instead of using instance variables, make an abstract method, e.g. "getVar()", in the parent class, and then in the child classes have that abstract method return a value. This works fine, the abstract method is enough to keep the parent class happy. But this is somewhat obfuscated. And it raises the important question of why I can be allowed to do this kind of thing with method dispatch, but not instance variable lookup? It's an inconsistency in the language.

A language like Java or C# (Java's evil step-brother) is chock-full of arbitrary rules and limitations like this. You have a small (by Ruby or Lisp standards) subset of very rigid constructs available to you, and if those constructs can't fit together the way you want, you certainly can't bend them; instead you build a mess to get yourself as close as you can, and then you have to do backflips to navigate through it. Whereas in Ruby or even moreso in Lisp, you have little bits of things that fit together in extremely arbitrary ways, and you can build really exciting and precise things out of those bits so that the end result does EXACTLY what you want, the way you want.

Is there a way in C# to declare an abstract INSTANCE VARIABLE? "abstract int var;"? I never even thought to try that today. If it does work or if there's something equivalent, I stand corrected. But today I ended up going with the second solution above.

October 30, 2007 @ 6:39 PM PDT
Cateogory: Programming
Tags: Lisp, Ruby, C_sharp

1 Comment

Quoth on July 29, 2011 @ 12:50 AM PDT

Yes, there is, effectively. You can declare properties in C# interfaces.

interface IThingWithInt
{
   int var { get; set; }
}