tags:

views:

60

answers:

3

Consider this scenario:

public class C
{
    private int _foo;

    public int Foo
    {
        get { return _foo; }

        [Obsolete("Modifying Foo through the setter may corrupt hash tables.  "
            + "Consider using the method 'ModifyFoo' instead.")]
        set { _foo = value; }
    }

    public C ModifyFoo( int foo )
    {
        // return a new instance of C
    }
}

Which doesn't compile:

error CS1667: Attribute 'Obsolete' is not valid on property or event accessors. It is only valid on 'class, struct, enum, constructor, method, property, indexer, field, event, interface, delegate' declarations.

Applying attributes to specifically the accessors is perfectly fine for any other attribute (provided that AttributeTargets.Method is set up in its usages, which is true for ObsoleteAttribute).

+1  A: 

In this case, if you were going to make it obsolete, wouldn't you just not include it? The point of the obsolete flag is to say there is a different (and better way of doing something).

In this case, you would probably want to make the change a breaking change and force people to update the code.

Kevin
Which is what I did. I'm just curious on why this is.
Tinister
+1  A: 

Why don't you just modify the property to use the code inModifyFoo?

Robert Harvey
Property setters have a void return type. `ModifyFoo` returns a new instance of C.
Tinister
Right you are. Your callers can call `ModifyFoo` without a return argument, and you can eliminate the setter. Or, throw an exception in the setter that returns the message "Use ModifyFoo to set this." (Not the greatest solution, but if you don't want a breaking change...)
Robert Harvey
You seem to misunderstand, which is my fault for the poor names in my posted scenario. The point is to enforce immutability. `c.Foo = 10; c.ModifyFoo(15);` isn't going to change the value of `c.Foo`, which will still be 10. `c.Foo = 10; c = c.ModifyFoo(15);` _will_ change `c.Foo`, since I'm reassigning `c`.
Tinister
Regardless, this is getting off-topic. While I'm most appreciative of your help, I'm not looking for a "solution", but rather asking why the language works this way.
Tinister
[Eric Lippert](http://stackoverflow.com/users/88656/eric-lippert) would know why.
Robert Harvey
+3  A: 

Clearly it is the compiler explicitly forbidding its use, it is not by accident. Hmya, why? A workaround for a restriction in the compiler seems pretty unlikely. I'd guess they decided to forbid it to avoid confusion to the programmer that gets the warning. Unless the message was well crafted, it would be quite confusing that it would show up inconsistently, depending on the property usage.

Hans Passant
I wonder if compilers for other .NET languages allow this, and what would happen if your C# code referenced an assembly where this was set up.
Tinister
Interesting comment. Tried it with VB.NET which does allow `<Obsolete>` on a setter. Unexpected result: the getter becomes obsolete as well. Now it does quack like a compiler restriction.
Hans Passant