Thursday, February 25, 2010

C# Equivalent to Java's "final"

From Stackoverflow:
I'm looking for the C# equivalent of Java's final. Does it exist?
Does C# have anything like the following:
public Foo(final int bar);
In the above example, bar is a read only variable and cannot be changed by Foo(). Is there any way to do this in C#?
For instance, maybe I have a long method that will be working with x, y, and z coordinates of some object (ints). I want to be absolutely certain that the function doesn't alter these values in any way, thereby corrupting the data. Thus, I would like to declare them readonly.

To clarify the question a little bit, the poster is wondering whether a C# equivalent to final exists that allows you to prevent the changing of parameter values.

The Java final keyword has a large number of uses, and C# uses several different keywords to account for several of those uses.  For example, to prevent a class from being inherited by a child class, you can use the sealed keyword in C# where you would use final in Java.  Or if you had a class level variable, or field that you didn't want the value to change you could use the const keyword and say "const int x;" where you would say "final int x" in Java.  For a detailed explanation of all the many uses of the Java keyword final, check out this link.

There is than one use of the final keyword that C# does not have an equivalent for.  When you pass a parameter to a method in Java, and you don't want that parameter's value to change within the scope of that method you can set it as final like this:

public Foo(final int bar) {
    bar++; //Compiler error on this line 
}

Its important to note that its the value that will not change when you use the final keyword here.  If we were to pass a reference to the object, we could call methods on that object that change the internal state of the object, but we couldn't set the reference to be a new object.  Example:

public Foo(final MyClass o) {
    o.ChangeState(); //Valid
    o = new MyClass(); //Compiler error
}

So where does that leave us in our C# code?  Actually it turns out that there really is no strong need for an equivalent in C#.  While it would certainly be nice to have the compiler check to make sure you aren't changing the parameter, in practice you really don't need it.  If you have run across situations where you really did find a true need for such a feature please let me know.

So if its not something you really need in C#, and Microsoft found reason to remove it, why has Sun/Oracle kept it in?  Anonymous classes.  In Java you can create an anonymous class in a method, and if a parameter is marked final that parameter becomes available to the anonymous class.  While my Java experience is fairly limited, GUI programming is where I have seen the most examples of it.  A good example would be adding an ActionListener to a JButton.

public JButton createButton(final MyClass o) {
    JButton button = new JButton();
    button.setAction(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            button.setText(o.toString());
        }
    });
}
In C#, we avoid the need for anonymous classes by using delegates as a reference to a method.  That means we can do this:

class MyForm extends Form
{
    MyClass o = new MyClass();

    public void MyForm()
    {
        var button = createButton();
    }

    public Button createButton()
    {
        var button = new Button();
        button.Click += button_Click;
    }

    public void button_Click(object sender, EventArgs e)
    {
        var button = (Button)sender;
        button.Text = o.ToString();
    }
}

In conclusion, there is no equivalent to final parameters in C# but with the help of delegates we are able to avoid needing them where they are used most in Java.

No comments:

Post a Comment

Post a Comment