Language Proposal (Strong Interfaces)

C

codymanix

Often you don't wish that clientcode does not depend on a certain
implementation of your methods:

class MyClass
{
public IList DoIt(){return new ArrayList();}
}

clientcode could now cast the return value in Arraylist. In a later version
you may find it more effective that your method returns an Array. This
change would break client code.

another example:

you want a list returned as readonly and, since wrappers are slow you simply
cast it to a interface that doesn't provide any modification methods.

IReadonlyList
{
public object this { get; }
}

INormalList : IReadonlyList
{
public object this { get; set;}
}

but now the problem is that the client could simply cast it back to a normal
list and modify it.

Now my proposal.

A modifier that, applied to a variable declaration or interface definition
forbids upcasting.
The result is an so called "strong interface" that cannot be upcasted no
matter what type the object is.

so that:

IReadonlyList r;
INormalList n = (INormalList)r;

will be caught by the compiler.
whereas

IReadonlyList r;
object o = r;
INormalList n = (INormalList)o;

cannot be detected at runtime, it has to throw an exception.

What do you think about this idea?
 
J

Jon Skeet [C# MVP]

codymanix said:
Often you don't wish that clientcode does not depend on a certain
implementation of your methods:

What do you think about this idea?

Well, it sounds (with your example) as though you're basically
advocating const-correctness, but in a different way - and one which
violates Liskov's Substitutability Principle.

I believe it's tackling a valid problem, but in an inappropriate way.
 
M

Martin Maat [EBL]

Often you don't wish that clientcode does not depend on a certain
implementation of your methods:

class MyClass
{
public IList DoIt(){return new ArrayList();}
}

clientcode could now cast the return value in Arraylist. In a later version
you may find it more effective that your method returns an Array. This
change would break client code.

This whole perception is wrong. You are basically saying "Type safety is
inflexible, we should toss around pointers and have the client decide what
type/interface to slap onto it. Far more convenient"

Then you go

"There is a problem with this though, it's not type safe. So let's disable
casting to fix that.".


If I cast a null to string and attempt to assign a value to it "my code will
break" (your words). I do not consider that a problem.

Designing any interface for casting is bad. Casting is something you do to
cut corners when things cannot possibly go wrong and all is determined. Your
example makes no sense whatsoever, if a method explicitely returns
ArrayList, casting it back to IList is as bad as returning a pointer. A
client receiving a (base) type can not nor should make any assumptions as to
the received type being anything more than that base type.

You may want to read about template classes, that may be the answer to your
problem.

Martin.
 
M

Magnus Lidbom

Your
example makes no sense whatsoever, if a method explicitly returns
ArrayList, casting it back to IList is as bad as returning a pointer.
Casting ArrayList to IList is a not necessary since it's an implicit
conversion and quite safe and appropriate. Perhaps you meant that if a
method signatures declares it to return an IList and the actual
implementation returns an ArrayList, upcasting the IList to ArrayList would
be a very bad idea since you are not using the exposed interface and the
internal implementation may change in the future.

/Magnus Lidbom
 
M

Magnus Lidbom

Jon Skeet said:
Well, it sounds (with your example) as though you're basically
advocating const-correctness, but in a different way - and one which
violates Liskov's Substitutability Principle.
I don't see it. How does his examples violate LSP? Implementations of
non-modifiable collections where the non-modifiable version inherits the
modifiable version most certainly does, but his examples deal only with
interfaces, and those he derives in the proper order.
I believe it's tackling a valid problem, but in an inappropriate way.
Agreed, but for other reasons:
http://groups.google.com/[email protected]&rnum=38


/Magnus Lidbom
 
M

Magnus Lidbom

Sami Vaaraniemi said:
Just to nitpick a bit: casting from a type to a more specific subtype is
actually called downcasting (at least in C++, don't know if C# parlance has
this reversed for some reason?).

Mea culpa.

/Magnus Lidbom
 
J

Jon Skeet [C# MVP]

Magnus Lidbom said:
I don't see it. How does his examples violate LSP? Implementations of
non-modifiable collections where the non-modifiable version inherits the
modifiable version most certainly does, but his examples deal only with
interfaces, and those he derives in the proper order.

You're right - oops :)
Agreed, but for other reasons:

<snip>

Sure.
 
S

Sami Vaaraniemi

Magnus Lidbom said:
Casting ArrayList to IList is a not necessary since it's an implicit
conversion and quite safe and appropriate. Perhaps you meant that if a
method signatures declares it to return an IList and the actual
implementation returns an ArrayList, upcasting the IList to ArrayList would
be a very bad idea since you are not using the exposed interface and the
internal implementation may change in the future.

Just to nitpick a bit: casting from a type to a more specific subtype is
actually called downcasting (at least in C++, don't know if C# parlance has
this reversed for some reason?). Upcasting goes from a subtype to a base
class, and the compiler can do this implicitly. I.e., casting an IList to an
ArrayList is a downcast.
 
C

cody

Often you don't wish that clientcode does not depend on a certain
This whole perception is wrong. You are basically saying "Type safety is
inflexible, we should toss around pointers and have the client decide what
type/interface to slap onto it. Far more convenient"

Huh? Since when does the client determine the type/interface?
Then you go

"There is a problem with this though, it's not type safe. So let's disable
casting to fix that.".


If I cast a null to string and attempt to assign a value to it "my code will
break" (your words). I do not consider that a problem.

Designing any interface for casting is bad. Casting is something you do to
cut corners when things cannot possibly go wrong and all is determined. Your
example makes no sense whatsoever, if a method explicitely returns
ArrayList, casting it back to IList is as bad as returning a pointer. A
client receiving a (base) type can not nor should make any assumptions as to
the received type being anything more than that base type.

You may want to read about template classes, that may be the answer to your
problem.


You did not fully understand my proposal. How could template classes help
here?
I *wish* to hide the implementation from the client so I return a generic
list but I *don't*
want that the client is able to upcast the IList to ArrayList or whatever
the certain implemenation is.

Additionally this technique can be useful when you want to return a
interface that doesn't allow
modification on the object, and you don't want that the client simply
upcasts your IReadOnlyList to IWriteableList.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top