Re: Anders Hejlsberg comment on immutable objects

From: Magnus Lidbom (magnus_lidbom_at_hotmail.com)
Date: 02/12/04


Date: Thu, 12 Feb 2004 01:29:24 +0100

On Mon, 9 Feb 2004 20:45:50 -0600, "Daniel O'Connell [C# MVP]"
<onyxkirx@--NOSPAM--comcast.net> wrote:

>> >> >
>> >> >Is not concept enough? I don't consider implementation enough at
>times.
>> >>
>> >> I don't understand what you mean. Enough what?
>> >Implicitly const classes are immutable by implementation. That makes the
>> >object immutable as either a sideeffect or a matter of const
>implementation.
>> >This is slightly different than an object being immutable at its core. It
>is
>> >subtle, I suppose.
>>
>> I'm sorry, I still don't understand what point you are trying to
>> make. What do you mean by "at its core"? I don't understand why you'd
>> consider it a sideaffect. The immutability could be accomplished
>> ,behind the scenes, by implicitly making all members and alll
>> instances of a class declared immutable const. That doesn't mean the
>> immutability of the class would be any less an conscious, intentional,
>> and explicit atribute of the class.
>
>Lemme reword this. Immutability is a design goal that is achieved by use of
>const, not an effect or result of const itself. It can be achieved *without*
>it, and has been. Immutability is a concept, a constant method is a
>different concept, even if one is used to achieve the other.

Agreed. Immutable means that all instances are const. That no visible
value or behavior in any instance can be changed. For reference types,
const ensures that no visible value or behavior of an instance can be
modified through a const reference an instance. For value types, const
ensures that no part of a value type instance can change.

<snip>

>> >> >It depends, I cast pretty much only to explicitly convert to an
>> >interface.
>> >>
>> >> Good catch. I failed to consider that quirk of the language. Since the
>> >> compiler already knows that the class implements the interface, and
>> >> that the cast will therefore always succeed, no warning should be
>> >> issued in this case. Semantically, this is not a cast. It is merely a
>> >> mechanism to allow you to unambiguously specify which method you
>> >> intended to call in the presence of naming conflicts when implementing
>> >> multiple interfaces.
>> >>
>> >Unfortunatly, the compiler can't actually know if the class implements
>the
>> >interface, atleast usually. A typed variable has no constraints on if the
>> >class provides an interface unless the type does. Derived classes are
>free
>> >to (re)implement interfaces. It may not be the cleanest thing but it is
>> >often reliable(preferably using as rather than (cast) operation, but
>still).
>>
>> I assumed you were talking about casting an instance of a specific
>> class to an interface that the instance's class implements explicitly.
>> If that's not what you mean, then either there is no need for a cast,
>> or we are talking about the sledgehammer that I would want to se a
>> warning for, at the highest warning level.
>
>Usually because of explicit implementation(or to decouple things, usually
>due to reflection.) However it can be difficult sometimes to know if an
>explicit implementation exists or not, just because a base class implements
>it implicitly, a derived class could reimplement it explicitly

Could you give an example where it would make sense for a subclass to
explicitly implement an interface that a base class implements
implicitly?

What if subclass of such a class overrides a method implicitly
implemented? Polymorphism is broken for such a class hierarchy.

Given that Foo exists in two versions, both implementations of
IBar.Foo, could you give an example where you would not consider the
class broken if instance.Foo != ((IBar)instance).Foo? Or if the result
of calling instance.Foo() was not the same as that of calling
((IBar)instance).Foo()?

If you can, how do you determine that the explicit' implementation is
the correct one to call? It may not be the most derived.

For my part, I consider such a class hierarchy fundamentally broken,
and as such, a problem I will deal with if I ever encounter it.

<snip>

>> >Safe is one thing, confusing and unapparent is another. Implicit
>conversions
>> >in most cases are an issue more of apparentability than anything else.
>Casts
>> >are apparent and a coder can deal with them, an implicit conversion is a
>> >risky thing that can cause code and behaviour to come into being that
>isn't
>> >expected.
>>
>> It should be neither confusing, unapparent nor risky. Implicit
>> conversions should occur only where the source type is an instance of
>> the target type as far as OO is concerned. As far as I know this is
>> the case for all built in implicit convertions.
>If you are working strictly with built in types you are lucky. I don't hav
>ethe time to analyze every piece of code\library I get nor can I
>realistically reject something simply because it provides an implicit
>conversion I don't like. I don't like to rely on implicit conversions
>otuside of some very limited situations

If you mean that you use cast to mark _improper_ implicit conversions,
then I'm all for it. Improper implicit conversions constitute a nasty
form of obfuscation. I define improper as any conversion not fitting
my comment above.

>If an object can't be used with the framework then why have a
>framework? As I illustrated before(different convo), you also technically
>loose access to ToString(), Equals(), GetHashCode(), the comparison operator
>and more or less any other method that the framework uses constantly.
>Without const in System.Object, const is broken.

It would certainly be very annoying, and inconvenient if the framework
was not reworked to be const aware. But it would be possible to work
around. Unless the ability to cast away const was removed as you've
suggested.

In the interest of clarity let me make it clear that I most definitely
want const in the framework. I just disagree with the opinion that
const would be useless if it wasn't. The discussion is almost
certainly purely academic however. I find it extremely hard to believe
that const would be implemented without proper modifications to the
appropriate parts of the framework.

>> >> >structs should be immutable by default, IMHO.
>> >>
>> >> Immutability is a relatively rare trait, making it the default would ,
>> >> in my opinion, be inappropriate. It certainly would break an immense
>> >> amount of code.
>> >Possibly, I should say immutability should be a design goal for value
>types.
>> >Due to their copy by value nature, you can't rely on a value type for
>much,
>> >immutability is often logical.
>>
>> This is not at all my experience. Actually, I don't know of a single
>> immutable struct type. Could you provide examples and a motivation for
>> this guideline?
>The primative .NET types are immutable.

int i = 0;
++i;

void ModyfyDate(ref DateTime date)
{
        date = DateTime.Now;
}

The reason that the primitives have no modifiers, besides operators,
it that, since they hold only one value, replacing the entire struct
is equivalent to changing that single value.

I do see how you could consider them immutable. They supply no
modifiers as such, besides operators. But the value of the variable is
the value type instance, and that value can be changed.

With value types, the variable's value is the object, not a reference
to the object, and immutable means that no part of an object can be
changed in any externally detectable way. No instance of a value type
in .Net can be immutable if not declared const.

<snipped area addressed by the above comment>

>> >> >> >Ideally, it would be possible to cast *to* const
>> >> >> That should be an implicit conversion. Zero runtime cost with a
>> >> >> classic implementation.
>> >> >
>> >> >I dislike implicit conversions,
>> >>
>> >> Even those, like the one above, that are 100% guaranteed to be safe?
>> >
>> >Except in limited situations, I'd rather see the explicit cast in code,
>> >mainly for maintaince sake.
>>
>> I don't understand this at all. How would placing a cast at the site
>> of every implicit convertion help maintainability? I'd expect the
>> opposite. A whole lot of code would still compile after changing the
>> type of a variable, because you explicitly cast it when passing it as
>> a base type or interface. You've written a whole lot of unnessessary
>> casts and moved refactoring problems from compile time to runtime, as
>> well as significantly increased the pure typing effort involved in
>> both the original coding and any refactoring. I see no gain in any of
>> this. Quite the opposite.
>
>Simply because the next guy can easily tell whats going on. With the
>exception of numeric conversions(mostly because thats how peoples minds
>work), I don't like implicit conversions. A cast to a base class isn't an
>implicit conversion, thats an implicit cast. Which is quite a different
>thing.

The type system, quite correctly, consider an ArrayList to be an
Object. No cast, implicit or otherwise, is employed to pass an
ArrayList as an Object or to invoke Object members on an ArrayList
instance. I'd consider casting to a base class obfuscation since a
cast is a clear indication that a dangerous conversion is performed
and this is simply not the case for such a convection.

Do you really write code like this?

int i = 1;
Console.WriteLine((object)i);
Type intType = ((Object)i).GetType();

Do you really consider code like that to improve maintainability and
legibility?

<snip>

Regards /Magnus Lidbom



Relevant Pages

  • Re: Anders Hejlsberg comment on immutable objects
    ... >>Implicitly const classes are immutable by implementation. ... The immutability could be accomplished ... often cast to get the interface instead of simply hoping that the entire ... >>are apparent and a coder can deal with them, an implicit conversion is a ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Anders Hejlsberg comment on immutable objects
    ... >object immutable as either a sideeffect or a matter of const implementation. ... The immutability could be accomplished ... >> look the other way while I cheat, by applying a cast, I expect it to ... >are apparent and a coder can deal with them, an implicit conversion is a ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Anders Hejlsberg comment on immutable objects
    ... Implicitly const classes are immutable by implementation. ... >>cast it away, and as I've said many times, everyone, me and you included, ... > Implicit conversions are quite different. ... I should say immutability should be a design goal for value types. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Anders Hejlsberg comment on immutable objects
    ... With respect to immutability, it's tricky because what you're saying ... </Anders Hejlsberg> ... fields declared mutable may be modified by a const member. ... <Anders Hejlsberg> ...
    (microsoft.public.dotnet.languages.csharp)