473,411 Members | 2,196 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,411 software developers and data experts.

feature question

hi all,
i first posted this on
http://msdn.microsoft.com/vcsharp/te...k/default.aspx
(ask a c# language designer) a couple of days ago, but no response so far...
therefore, i am pasting it here as well... enjoy!

(you can skip to the source at the end of the message if you like...)

Consider:

1) a class relationships A -> B and C -> D
2) a delegate declaration "delegate C DF (B b);"
3) a function with signature "D F (A a);"

According to C# syntax and semantics, an instance of the delegate DF
cannot be created from the function F, as the parameter types and the
return type do not match the delegate declaration.

I would argue that from formal language type theory, it should be
possible, because of polymorphism.

Suppose this hypothetic code:

{
DF d = new DF(F);

B b = new ...

C c = d(b);
}

I have no reasons to believe that such code should break. In fact:

1) d is an instance of DF using function F

2) d is called with parameter b which is of type B, which derives from
A,
therefore F can be called itself with b

3) d's result is assigned to c, which is of type C, which type D derives
from. Because F returns D, it's result is assignable to C-typed
objects...

In summary I would argue that it is type-safe to allow this. Further I
don't think that it adds any further complexity in the language and it
is something worth having. I personally expected to see it there, was
disappointed when it I did not, and I have needed it a number of times.

One fact that confirms my thesis is that if we write the following
function:

C auxF (B b)
{
return F(b);
}

The new auxF is compatible with the delegate and does exactly what we
want.
To refine my question further I would say: Why do we need auxF???

Please find a "working" C# program below that illustrates the issue!

Please outline the reasons for which this is not part of the C#
language.
Do not hesitate to contact me personally if you need more information
regarding this question.

Best Regards,
Kamen Yotov
ka***@yotov.org
http://yotov.org

using System;

class A {}
class B: A {}
class C {}
class D: C {}

delegate C DF (B b);

class Run
{
static D F (A a)
{
return new D();
}

static C auxF (B b) // I would like to get rid of this function
{
return F(b);
}

static void Main(string[] args)
{
DF d = new DF(auxF); // I want "new DF(F)" here!
B b = new B();

Console.WriteLine(d(b));
}
}


Nov 15 '05 #1
18 1628
Makes sense. This does not create any hole in the type system and it could
be handy in some cases.

The same reasoning could be applied to overrides:

1) a class relationships A -> B and C -> D
2) a base method with signature "C BM(B b);"
3) an override with signature "D OM(A a);"

Why doesn't C# let you override BM with OM in this case? Quite often, I
would like to do this, especially replacing the return type (C) by a more
specialized one (D) into the override, but I cannot do it, I am forced to
use C as return type and then my code is polluted by (D) casts.

To me, this is more rigorous than the following:

A[] aArray = new B[10];

which will let you store objects that don't derive from B into aArray. The
compiler allows it and you get a runtime exception!

Bruno.

"Kamen Yotov" <ka***@yotov.org> a écrit dans le message de
news:eY**************@TK2MSFTNGP09.phx.gbl...
hi all,
i first posted this on
http://msdn.microsoft.com/vcsharp/te...k/default.aspx
(ask a c# language designer) a couple of days ago, but no response so far... therefore, i am pasting it here as well... enjoy!

(you can skip to the source at the end of the message if you like...)

Consider:

1) a class relationships A -> B and C -> D
2) a delegate declaration "delegate C DF (B b);"
3) a function with signature "D F (A a);"

According to C# syntax and semantics, an instance of the delegate DF
cannot be created from the function F, as the parameter types and the
return type do not match the delegate declaration.

I would argue that from formal language type theory, it should be
possible, because of polymorphism.

Suppose this hypothetic code:

{
DF d = new DF(F);

B b = new ...

C c = d(b);
}

I have no reasons to believe that such code should break. In fact:

1) d is an instance of DF using function F

2) d is called with parameter b which is of type B, which derives from
A,
therefore F can be called itself with b

3) d's result is assigned to c, which is of type C, which type D derives
from. Because F returns D, it's result is assignable to C-typed
objects...

In summary I would argue that it is type-safe to allow this. Further I
don't think that it adds any further complexity in the language and it
is something worth having. I personally expected to see it there, was
disappointed when it I did not, and I have needed it a number of times.

One fact that confirms my thesis is that if we write the following
function:

C auxF (B b)
{
return F(b);
}

The new auxF is compatible with the delegate and does exactly what we
want.
To refine my question further I would say: Why do we need auxF???

Please find a "working" C# program below that illustrates the issue!

Please outline the reasons for which this is not part of the C#
language.
Do not hesitate to contact me personally if you need more information
regarding this question.

Best Regards,
Kamen Yotov
ka***@yotov.org
http://yotov.org

using System;

class A {}
class B: A {}
class C {}
class D: C {}

delegate C DF (B b);

class Run
{
static D F (A a)
{
return new D();
}

static C auxF (B b) // I would like to get rid of this function
{
return F(b);
}

static void Main(string[] args)
{
DF d = new DF(auxF); // I want "new DF(F)" here!
B b = new B();

Console.WriteLine(d(b));
}
}

Nov 15 '05 #2
Ooop, my post is not very clear. You should read:

1) a class relationships A -> B and C -> D
2) a base method BM with signature "C M(B b);"
3) an override OM with signature "D M(A a);"

Typical example is the Object/Factory pattern where you have two parallel
hierarchies: BaseObject, DerivedObject on one side and BaseFactory,
DerivedFactory on the other side. You want to define
BaseFactory GetFactory() in the BaseObject class
and override it as:
DerivedFactory GetFactory() in the DerivedObject class

There are ways around it (with the "new" keyword) but things would be
cleaner if the type system was a bit smarter.

Note: GetFactory() can be replaced by a get-only Factory property, this does
not change the point above. On the other hand, we cannot make the property
get/set because then we have a typing problem on the set (the override set
accessor has a more restrictive signature than the base accessor).

Bruno

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> a écrit dans le message de
news:%2******************@TK2MSFTNGP10.phx.gbl...
Makes sense. This does not create any hole in the type system and it could
be handy in some cases.

The same reasoning could be applied to overrides:

1) a class relationships A -> B and C -> D
2) a base method with signature "C BM(B b);"
3) an override with signature "D OM(A a);"

Why doesn't C# let you override BM with OM in this case? Quite often, I
would like to do this, especially replacing the return type (C) by a more
specialized one (D) into the override, but I cannot do it, I am forced to
use C as return type and then my code is polluted by (D) casts.

To me, this is more rigorous than the following:

A[] aArray = new B[10];

which will let you store objects that don't derive from B into aArray. The
compiler allows it and you get a runtime exception!

Bruno.

"Kamen Yotov" <ka***@yotov.org> a écrit dans le message de
news:eY**************@TK2MSFTNGP09.phx.gbl...
hi all,
i first posted this on
http://msdn.microsoft.com/vcsharp/te...k/default.aspx
(ask a c# language designer) a couple of days ago, but no response so

far...
therefore, i am pasting it here as well... enjoy!

(you can skip to the source at the end of the message if you like...)

Consider:

1) a class relationships A -> B and C -> D
2) a delegate declaration "delegate C DF (B b);"
3) a function with signature "D F (A a);"

According to C# syntax and semantics, an instance of the delegate DF
cannot be created from the function F, as the parameter types and the
return type do not match the delegate declaration.

I would argue that from formal language type theory, it should be
possible, because of polymorphism.

Suppose this hypothetic code:

{
DF d = new DF(F);

B b = new ...

C c = d(b);
}

I have no reasons to believe that such code should break. In fact:

1) d is an instance of DF using function F

2) d is called with parameter b which is of type B, which derives from
A,
therefore F can be called itself with b

3) d's result is assigned to c, which is of type C, which type D derives
from. Because F returns D, it's result is assignable to C-typed
objects...

In summary I would argue that it is type-safe to allow this. Further I
don't think that it adds any further complexity in the language and it
is something worth having. I personally expected to see it there, was
disappointed when it I did not, and I have needed it a number of times.

One fact that confirms my thesis is that if we write the following
function:

C auxF (B b)
{
return F(b);
}

The new auxF is compatible with the delegate and does exactly what we
want.
To refine my question further I would say: Why do we need auxF???

Please find a "working" C# program below that illustrates the issue!

Please outline the reasons for which this is not part of the C#
language.
Do not hesitate to contact me personally if you need more information
regarding this question.

Best Regards,
Kamen Yotov
ka***@yotov.org
http://yotov.org

using System;

class A {}
class B: A {}
class C {}
class D: C {}

delegate C DF (B b);

class Run
{
static D F (A a)
{
return new D();
}

static C auxF (B b) // I would like to get rid of this function
{
return F(b);
}

static void Main(string[] args)
{
DF d = new DF(auxF); // I want "new DF(F)" here!
B b = new B();

Console.WriteLine(d(b));
}
}


Nov 15 '05 #3
While the return type doesn't present a problem since type D is always also
type C, the input parameter is a problem. Your delegate DF is a guarantee
that you can call that method with a parameter of type B or any subclass of
B.

If I have type Q -> B and you pass me a delegate d of type DF but it can
only accept a parameter of type A then it will compile fine but when I try
to invoke the delegate with a parameter of type Q I will get a nasty runtime
error because you've broken the contract that I can use any subclass of B
with that delegate.

There is also a similar problem with overrides. The base class guarantees
that the method can be called with any subclass of the parameter type but
the override narrows that guarantee so the method can no longer be used
polymorphically.

I think that overriding the return types is simpler since it doesn't, in
fact, violate the interface contract and I'm sure overriding the parameter
types could be done but I'm not sure it would be desirable and I don't think
it would be simple.

"Kamen Yotov" <ka***@yotov.org> wrote in message
news:eY**************@TK2MSFTNGP09.phx.gbl...
hi all,
i first posted this on
http://msdn.microsoft.com/vcsharp/te...k/default.aspx
(ask a c# language designer) a couple of days ago, but no response so far... therefore, i am pasting it here as well... enjoy!

(you can skip to the source at the end of the message if you like...)

Consider:

1) a class relationships A -> B and C -> D
2) a delegate declaration "delegate C DF (B b);"
3) a function with signature "D F (A a);"

According to C# syntax and semantics, an instance of the delegate DF
cannot be created from the function F, as the parameter types and the
return type do not match the delegate declaration.

I would argue that from formal language type theory, it should be
possible, because of polymorphism.

Suppose this hypothetic code:

{
DF d = new DF(F);

B b = new ...

C c = d(b);
}

I have no reasons to believe that such code should break. In fact:

1) d is an instance of DF using function F

2) d is called with parameter b which is of type B, which derives from
A,
therefore F can be called itself with b

3) d's result is assigned to c, which is of type C, which type D derives
from. Because F returns D, it's result is assignable to C-typed
objects...

In summary I would argue that it is type-safe to allow this. Further I
don't think that it adds any further complexity in the language and it
is something worth having. I personally expected to see it there, was
disappointed when it I did not, and I have needed it a number of times.

One fact that confirms my thesis is that if we write the following
function:

C auxF (B b)
{
return F(b);
}

The new auxF is compatible with the delegate and does exactly what we
want.
To refine my question further I would say: Why do we need auxF???

Please find a "working" C# program below that illustrates the issue!

Please outline the reasons for which this is not part of the C#
language.
Do not hesitate to contact me personally if you need more information
regarding this question.

Best Regards,
Kamen Yotov
ka***@yotov.org
http://yotov.org

using System;

class A {}
class B: A {}
class C {}
class D: C {}

delegate C DF (B b);

class Run
{
static D F (A a)
{
return new D();
}

static C auxF (B b) // I would like to get rid of this function
{
return F(b);
}

static void Main(string[] args)
{
DF d = new DF(auxF); // I want "new DF(F)" here!
B b = new B();

Console.WriteLine(d(b));
}
}

Nov 15 '05 #4

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl...
Ooop, my post is not very clear. You should read:

1) a class relationships A -> B and C -> D
2) a base method BM with signature "C M(B b);"
3) an override OM with signature "D M(A a);"

Typical example is the Object/Factory pattern where you have two parallel
hierarchies: BaseObject, DerivedObject on one side and BaseFactory,
DerivedFactory on the other side. You want to define
BaseFactory GetFactory() in the BaseObject class
and override it as:
DerivedFactory GetFactory() in the DerivedObject class

There are ways around it (with the "new" keyword) but things would be
cleaner if the type system was a bit smarter.

Frankly, why are you using a derived factory system if the derived class
needs to be cast to to use it? You should be designing the system to rely on
the functionality of C, otherwise I really don't think there is much point
to a base class.
By using casts and implicit knowledge of type, you break most of the
benifits of using a factory system, where in you shouldn't have to need to
know the exact type of the object, just that it derives from your target
object or implements a given interface. If D provides all the functionality,
then shouldn't D be the base class? If you know you are always going to be
using D, why bother with a factory? Outside of perhaps the base class
providing strong caching or something(generics should help with this), I see
little need for derivation in your situation.
Can you explain this to me in more detail?
Note: GetFactory() can be replaced by a get-only Factory property, this does not change the point above. On the other hand, we cannot make the property
get/set because then we have a typing problem on the set (the override set
accessor has a more restrictive signature than the base accessor).

Bruno

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> a $BqD(Brit dans le message de news:%2******************@TK2MSFTNGP10.phx.gbl...
Makes sense. This does not create any hole in the type system and it could be handy in some cases.

The same reasoning could be applied to overrides:

1) a class relationships A -> B and C -> D
2) a base method with signature "C BM(B b);"
3) an override with signature "D OM(A a);"

Why doesn't C# let you override BM with OM in this case? Quite often, I
would like to do this, especially replacing the return type (C) by a more specialized one (D) into the override, but I cannot do it, I am forced to use C as return type and then my code is polluted by (D) casts.

To me, this is more rigorous than the following:

A[] aArray = new B[10];

which will let you store objects that don't derive from B into aArray. The compiler allows it and you get a runtime exception!

Bruno.

"Kamen Yotov" <ka***@yotov.org> a $BqD(Brit dans le message de
news:eY**************@TK2MSFTNGP09.phx.gbl...
hi all,
i first posted this on
http://msdn.microsoft.com/vcsharp/te...k/default.aspx
(ask a c# language designer) a couple of days ago, but no response so

far...
therefore, i am pasting it here as well... enjoy!

(you can skip to the source at the end of the message if you like...)

Consider:

1) a class relationships A -> B and C -> D
2) a delegate declaration "delegate C DF (B b);"
3) a function with signature "D F (A a);"

According to C# syntax and semantics, an instance of the delegate DF
cannot be created from the function F, as the parameter types and the
return type do not match the delegate declaration.

I would argue that from formal language type theory, it should be
possible, because of polymorphism.

Suppose this hypothetic code:

{
DF d = new DF(F);

B b = new ...

C c = d(b);
}

I have no reasons to believe that such code should break. In fact:

1) d is an instance of DF using function F

2) d is called with parameter b which is of type B, which derives from
A,
therefore F can be called itself with b

3) d's result is assigned to c, which is of type C, which type D derives from. Because F returns D, it's result is assignable to C-typed
objects...

In summary I would argue that it is type-safe to allow this. Further I
don't think that it adds any further complexity in the language and it
is something worth having. I personally expected to see it there, was
disappointed when it I did not, and I have needed it a number of times.
One fact that confirms my thesis is that if we write the following
function:

C auxF (B b)
{
return F(b);
}

The new auxF is compatible with the delegate and does exactly what we
want.
To refine my question further I would say: Why do we need auxF???

Please find a "working" C# program below that illustrates the issue!

Please outline the reasons for which this is not part of the C#
language.
Do not hesitate to contact me personally if you need more information
regarding this question.

Best Regards,
Kamen Yotov
ka***@yotov.org
http://yotov.org

using System;

class A {}
class B: A {}
class C {}
class D: C {}

delegate C DF (B b);

class Run
{
static D F (A a)
{
return new D();
}

static C auxF (B b) // I would like to get rid of this function
{
return F(b);
}

static void Main(string[] args)
{
DF d = new DF(auxF); // I want "new DF(F)" here!
B b = new B();

Console.WriteLine(d(b));
}
}



Nov 15 '05 #5
This is usually known as "delegate contravariance" (assuming I've got my co
and contras correct today (covariance would be on the return type)), and
while it isn't supported in C# now, it may show up in the future.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://weblogs.asp.net/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
"Kamen Yotov" <ka***@yotov.org> wrote in message
news:eY**************@TK2MSFTNGP09.phx.gbl...
hi all,
i first posted this on
http://msdn.microsoft.com/vcsharp/te...k/default.aspx
(ask a c# language designer) a couple of days ago, but no response so far... therefore, i am pasting it here as well... enjoy!

(you can skip to the source at the end of the message if you like...)

Consider:

1) a class relationships A -> B and C -> D
2) a delegate declaration "delegate C DF (B b);"
3) a function with signature "D F (A a);"

According to C# syntax and semantics, an instance of the delegate DF
cannot be created from the function F, as the parameter types and the
return type do not match the delegate declaration.

I would argue that from formal language type theory, it should be
possible, because of polymorphism.

Suppose this hypothetic code:

{
DF d = new DF(F);

B b = new ...

C c = d(b);
}

I have no reasons to believe that such code should break. In fact:

1) d is an instance of DF using function F

2) d is called with parameter b which is of type B, which derives from
A,
therefore F can be called itself with b

3) d's result is assigned to c, which is of type C, which type D derives
from. Because F returns D, it's result is assignable to C-typed
objects...

In summary I would argue that it is type-safe to allow this. Further I
don't think that it adds any further complexity in the language and it
is something worth having. I personally expected to see it there, was
disappointed when it I did not, and I have needed it a number of times.

One fact that confirms my thesis is that if we write the following
function:

C auxF (B b)
{
return F(b);
}

The new auxF is compatible with the delegate and does exactly what we
want.
To refine my question further I would say: Why do we need auxF???

Please find a "working" C# program below that illustrates the issue!

Please outline the reasons for which this is not part of the C#
language.
Do not hesitate to contact me personally if you need more information
regarding this question.

Best Regards,
Kamen Yotov
ka***@yotov.org
http://yotov.org

using System;

class A {}
class B: A {}
class C {}
class D: C {}

delegate C DF (B b);

class Run
{
static D F (A a)
{
return new D();
}

static C auxF (B b) // I would like to get rid of this function
{
return F(b);
}

static void Main(string[] args)
{
DF d = new DF(auxF); // I want "new DF(F)" here!
B b = new B();

Console.WriteLine(d(b));
}
}

Nov 15 '05 #6
There is a misunderstanding.
When I say "A -> B", I mean "B derives from A".
It is not possible "A -> B" and "Q -> B", at least in C#.
Let me know if you still thing you have a case...

Kamen

"Stephen Martin" <sm*****@removethis.emsoft.andthis.ca> wrote in message
news:%2****************@TK2MSFTNGP12.phx.gbl...
While the return type doesn't present a problem since type D is always also type C, the input parameter is a problem. Your delegate DF is a guarantee
that you can call that method with a parameter of type B or any subclass of B.

If I have type Q -> B and you pass me a delegate d of type DF but it can
only accept a parameter of type A then it will compile fine but when I try
to invoke the delegate with a parameter of type Q I will get a nasty runtime error because you've broken the contract that I can use any subclass of B
with that delegate.

There is also a similar problem with overrides. The base class guarantees
that the method can be called with any subclass of the parameter type but
the override narrows that guarantee so the method can no longer be used
polymorphically.

I think that overriding the return types is simpler since it doesn't, in
fact, violate the interface contract and I'm sure overriding the parameter
types could be done but I'm not sure it would be desirable and I don't think it would be simple.

"Kamen Yotov" <ka***@yotov.org> wrote in message
news:eY**************@TK2MSFTNGP09.phx.gbl...
hi all,
i first posted this on
http://msdn.microsoft.com/vcsharp/te...k/default.aspx
(ask a c# language designer) a couple of days ago, but no response so

far...
therefore, i am pasting it here as well... enjoy!

(you can skip to the source at the end of the message if you like...)

Consider:

1) a class relationships A -> B and C -> D
2) a delegate declaration "delegate C DF (B b);"
3) a function with signature "D F (A a);"

According to C# syntax and semantics, an instance of the delegate DF
cannot be created from the function F, as the parameter types and the
return type do not match the delegate declaration.

I would argue that from formal language type theory, it should be
possible, because of polymorphism.

Suppose this hypothetic code:

{
DF d = new DF(F);

B b = new ...

C c = d(b);
}

I have no reasons to believe that such code should break. In fact:

1) d is an instance of DF using function F

2) d is called with parameter b which is of type B, which derives from
A,
therefore F can be called itself with b

3) d's result is assigned to c, which is of type C, which type D derives
from. Because F returns D, it's result is assignable to C-typed
objects...

In summary I would argue that it is type-safe to allow this. Further I
don't think that it adds any further complexity in the language and it
is something worth having. I personally expected to see it there, was
disappointed when it I did not, and I have needed it a number of times.

One fact that confirms my thesis is that if we write the following
function:

C auxF (B b)
{
return F(b);
}

The new auxF is compatible with the delegate and does exactly what we
want.
To refine my question further I would say: Why do we need auxF???

Please find a "working" C# program below that illustrates the issue!

Please outline the reasons for which this is not part of the C#
language.
Do not hesitate to contact me personally if you need more information
regarding this question.

Best Regards,
Kamen Yotov
ka***@yotov.org
http://yotov.org

using System;

class A {}
class B: A {}
class C {}
class D: C {}

delegate C DF (B b);

class Run
{
static D F (A a)
{
return new D();
}

static C auxF (B b) // I would like to get rid of this function
{
return F(b);
}

static void Main(string[] args)
{
DF d = new DF(auxF); // I want "new DF(F)" here!
B b = new B();

Console.WriteLine(d(b));
}
}


Nov 15 '05 #7
Hi,

My apologies, I tend to read this type of thing using the UML standard with
the arrow pointing to the base class. So, I thought you were arguing for
parameter covariance something I generally believe to be a very poor idea.

"Kamen Yotov" <ka***@yotov.org> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
There is a misunderstanding.
When I say "A -> B", I mean "B derives from A".
It is not possible "A -> B" and "Q -> B", at least in C#.
Let me know if you still thing you have a case...

Kamen
<snip>

Nov 15 '05 #8
> Frankly, why are you using a derived factory system if the derived class
needs to be cast to to use it? You should be designing the system to rely on the functionality of C, otherwise I really don't think there is much point
to a base class.
By using casts and implicit knowledge of type, you break most of the
benifits of using a factory system, where in you shouldn't have to need to
know the exact type of the object, just that it derives from your target
object or implements a given interface. If D provides all the functionality, then shouldn't D be the base class? If you know you are always going to be
using D, why bother with a factory? Outside of perhaps the base class
providing strong caching or something(generics should help with this), I see little need for derivation in your situation.
Can you explain this to me in more detail?


My factories do a lot more than instanciate objects, they also hold a wealth
of meta information about the objects (more than I could reasonably encode
in attributes, which is why I introduced Factory classes).
Then, I use these factories in two contexts:

1) In BaseObject, I have generic methods that operate on objects by
accessing the meta information that I can find in their factory. So, these
methods call baseObject.GetFactory() to get the BaseFactory, and then they
use the meta information of the BaseFactory to their job in a very generic
way. At this level, I don't have any casts and I don't have any "implicit
knowledge" of the type.

2) In DerivedObject, I have specialized methods that are implemented by
passing a piece of meta information that I get from DerivedFactory to a
generic method implemented at the BaseObject level. A typical example is:

public string Foo { return
GetStringValue(((DerivedFactory)GetFactory()).FooP roperty); }
// GetStringValue is a generic method inherited from BaseObject
// FooProperty is a piece of meta information that I find in
DerivedFactory but not in BaseFactory.

So, here, inside DerivedObject, I still need to access the factory, but this
time, I need to get the "derived" factory, not the base factory. So, I would
be really nice if I could override GetFactory() as:

public DerivedFactory GetFactory() { return
(DerivedFactory)base.GetFactory(); }

I hope that this example will explain why it may be interesting to have an
override that "casts" in a subclass. The intent is not to use it at the base
level (which would be against good OO programming practices), but to use it
at the derived level.

In fact, C# lets me redefine GetFactory() as returning DerivedFactory in the
DerivedObject class but I have to use the "new" keyword to keep the C#
compiler happy. I find it a bit strange that I have to use new here, because
the method of the derived class has basically the same semantics as the
method of the base class (it returns the object's factory), and new is
supposed to solve the case where you have a name clash but the methods have
different semantics.

The real fix to this would be to have a more advanced typing system. You
should be able to say that:
BaseFactory is Factory<BaseObject>
DerivedFactory is Factory<DerivedObject>
T.GetFactory() returns Factory<T>

Current C# does not let you do that. I hope that Whidbey generics will let
us do it, but I have not tested this yet.

In any case, I think that the point made by Kamen Yotof is very valid. From
a theoretical standpoint, there is no reason to reject the type
compatibility rule that he is proposing because this rule does not create
any hole in the type system, and this rule could be extended to "overrides".
But there are probably some "practical" issues that led the C# designer to
stick to a much stricter rule.

Bruno.

Nov 15 '05 #9

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:eO*************@TK2MSFTNGP12.phx.gbl...
Frankly, why are you using a derived factory system if the derived class
needs to be cast to to use it? You should be designing the system to rely
on
the functionality of C, otherwise I really don't think there is much
point to a base class.
By using casts and implicit knowledge of type, you break most of the
benifits of using a factory system, where in you shouldn't have to need to know the exact type of the object, just that it derives from your target
object or implements a given interface. If D provides all the

functionality,
then shouldn't D be the base class? If you know you are always going to be using D, why bother with a factory? Outside of perhaps the base class
providing strong caching or something(generics should help with this), I

see
little need for derivation in your situation.
Can you explain this to me in more detail?


My factories do a lot more than instanciate objects, they also hold a

wealth of meta information about the objects (more than I could reasonably encode
in attributes, which is why I introduced Factory classes).
Then, I use these factories in two contexts:

1) In BaseObject, I have generic methods that operate on objects by
accessing the meta information that I can find in their factory. So, these
methods call baseObject.GetFactory() to get the BaseFactory, and then they
use the meta information of the BaseFactory to their job in a very generic
way. At this level, I don't have any casts and I don't have any "implicit
knowledge" of the type.

2) In DerivedObject, I have specialized methods that are implemented by
passing a piece of meta information that I get from DerivedFactory to a
generic method implemented at the BaseObject level. A typical example is:

public string Foo { return
GetStringValue(((DerivedFactory)GetFactory()).FooP roperty); }
// GetStringValue is a generic method inherited from BaseObject
// FooProperty is a piece of meta information that I find in
DerivedFactory but not in BaseFactory.

So, here, inside DerivedObject, I still need to access the factory, but this time, I need to get the "derived" factory, not the base factory. So, I would be really nice if I could override GetFactory() as:

public DerivedFactory GetFactory() { return
(DerivedFactory)base.GetFactory(); }

I hope that this example will explain why it may be interesting to have an
override that "casts" in a subclass. The intent is not to use it at the base level (which would be against good OO programming practices), but to use it at the derived level.

In fact, C# lets me redefine GetFactory() as returning DerivedFactory in the DerivedObject class but I have to use the "new" keyword to keep the C#
compiler happy. I find it a bit strange that I have to use new here, because the method of the derived class has basically the same semantics as the
method of the base class (it returns the object's factory), and new is
supposed to solve the case where you have a name clash but the methods have different semantics.

The real fix to this would be to have a more advanced typing system. You
should be able to say that:
BaseFactory is Factory<BaseObject>
DerivedFactory is Factory<DerivedObject>
T.GetFactory() returns Factory<T>
This does sound like a generic factory more than a what I suspected(I would
actually probably not derive the factory itself, just the functionality
needed). but this should work, basically

public class BaseFactory<T> : Factory<T>
where T : BaseClass
{

}

public class DerivedFactory<T> : BaseFactory<T>
where T : DerivedClass
{

}

Should be sufficent. Its not perfect but it is possible. Current C# does not let you do that. I hope that Whidbey generics will let
us do it, but I have not tested this yet.

In any case, I think that the point made by Kamen Yotof is very valid. From a theoretical standpoint, there is no reason to reject the type
compatibility rule that he is proposing because this rule does not create
any hole in the type system, and this rule could be extended to "overrides". But there are probably some "practical" issues that led the C# designer to
stick to a much stricter rule.
Its more simplicity. It makes it easier to work with the language as a
whole.
Bruno.


Nov 15 '05 #10
<bottom-posted>

"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:O8**************@TK2MSFTNGP12.phx.gbl...

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:eO*************@TK2MSFTNGP12.phx.gbl...
Frankly, why are you using a derived factory system if the derived class needs to be cast to to use it? You should be designing the system to rely
on
the functionality of C, otherwise I really don't think there is much point to a base class.
By using casts and implicit knowledge of type, you break most of the
benifits of using a factory system, where in you shouldn't have to need
to
know the exact type of the object, just that it derives from your
target object or implements a given interface. If D provides all the functionality,
then shouldn't D be the base class? If you know you are always going

to be using D, why bother with a factory? Outside of perhaps the base class
providing strong caching or something(generics should help with this),
I see
little need for derivation in your situation.
Can you explain this to me in more detail?


My factories do a lot more than instanciate objects, they also hold a

wealth
of meta information about the objects (more than I could reasonably encode in attributes, which is why I introduced Factory classes).
Then, I use these factories in two contexts:

1) In BaseObject, I have generic methods that operate on objects by
accessing the meta information that I can find in their factory. So, these methods call baseObject.GetFactory() to get the BaseFactory, and then they use the meta information of the BaseFactory to their job in a very generic way. At this level, I don't have any casts and I don't have any "implicit knowledge" of the type.

2) In DerivedObject, I have specialized methods that are implemented by
passing a piece of meta information that I get from DerivedFactory to a
generic method implemented at the BaseObject level. A typical example is:
public string Foo { return
GetStringValue(((DerivedFactory)GetFactory()).FooP roperty); }
// GetStringValue is a generic method inherited from BaseObject
// FooProperty is a piece of meta information that I find in
DerivedFactory but not in BaseFactory.

So, here, inside DerivedObject, I still need to access the factory, but

this
time, I need to get the "derived" factory, not the base factory. So, I

would
be really nice if I could override GetFactory() as:

public DerivedFactory GetFactory() { return
(DerivedFactory)base.GetFactory(); }

I hope that this example will explain why it may be interesting to have an override that "casts" in a subclass. The intent is not to use it at the

base
level (which would be against good OO programming practices), but to use

it
at the derived level.

In fact, C# lets me redefine GetFactory() as returning DerivedFactory in

the
DerivedObject class but I have to use the "new" keyword to keep the C#
compiler happy. I find it a bit strange that I have to use new here,

because
the method of the derived class has basically the same semantics as the
method of the base class (it returns the object's factory), and new is
supposed to solve the case where you have a name clash but the methods

have
different semantics.

The real fix to this would be to have a more advanced typing system. You
should be able to say that:
BaseFactory is Factory<BaseObject>
DerivedFactory is Factory<DerivedObject>
T.GetFactory() returns Factory<T>

This does sound like a generic factory more than a what I suspected(I

would actually probably not derive the factory itself, just the functionality
needed). but this should work, basically

public class BaseFactory<T> : Factory<T>
where T : BaseClass
{

}

public class DerivedFactory<T> : BaseFactory<T>
where T : DerivedClass
{

}

Should be sufficent. Its not perfect but it is possible.
Current C# does not let you do that. I hope that Whidbey generics will let us do it, but I have not tested this yet.

In any case, I think that the point made by Kamen Yotof is very valid.

From
a theoretical standpoint, there is no reason to reject the type
compatibility rule that he is proposing because this rule does not create any hole in the type system, and this rule could be extended to

"overrides".
But there are probably some "practical" issues that led the C# designer to stick to a much stricter rule.


Its more simplicity. It makes it easier to work with the language as a
whole.


If less rules make a language easier to work with, then write in Java, not
C#.
There is a balance to it, and I believe it is important to be careful when
drawing the line...
Each point of the spectrum has its advantages / disadvantages.

Java - safe, least expressive, easiest to learn (simplest formal grammar),
verbose, not for large projects, good to teach

C# - safe by default, more expressive, somewhat more to learn, somewhat more
concise, good for large projects, ok to teach

C++ - unsafe, most expressive, most to learn, very concise, good for fooling
around with it (works for large projects if you are disciplined enough),
terrible to teach

Frankly I see C# as a combination of C++ and Delphi with some nasty C++
taken out and some "hot new" stuff put in.
My ideal for C# would be to allow everything that is safe!!!

Therefore my initial question about this "delegate contravariance", as Eric
G. refers to it.
In my opinion, if the language supports Polymorphism (which C#, like any
other OOP language does), it should support this feature also. Otherwise,
the type system is crippled.

Omitting the feature does not make the language simpler, on the contrary -
it creates more headaches for the programmer.
Nov 15 '05 #11
> Its more simplicity. It makes it easier to work with the language as a
whole.


Simpler for the people who write compilers, I agree.
Simpler for the people who use the language, this is more debatable.

Bruno.
Nov 15 '05 #12
> Java - safe, least expressive, easiest to learn (simplest formal grammar),
verbose, not for large projects, good to teach
"verbose" is somewhat excessive. Of course, class declarations are a bit
more verbose and you don't have the nice property and indexer syntax. But
for the rest of it, Java is quite concise. We are still very far from COBOL
or even ADA.

C# - safe by default, more expressive, somewhat more to learn, somewhat more concise, good for large projects, ok to teach

C++ - unsafe, most expressive, most to learn, very concise, good for fooling around with it (works for large projects if you are disciplined enough),
terrible to teach

Frankly I see C# as a combination of C++ and Delphi with some nasty C++
taken out and some "hot new" stuff put in.
My ideal for C# would be to allow everything that is safe!!!


To me, C# is what Java would have become if the Java guys had accepted that
Microsoft infuse its good ideas into it. J++ is the "missing link" between
Java and C#: Java + conditional compilation + delegates + P/Invoke
(J/Direct), etc.
So, I think that C# has more genes in common with Java than with C++.
Java is C++ with the nasty stuff taken out.

The C++ heritage is just a marketing ploy to avoid nasty comments about
Microsoft copying Java.

Bruno
Nov 15 '05 #13

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:Oz****************@tk2msftngp13.phx.gbl...
Java - safe, least expressive, easiest to learn (simplest formal grammar), verbose, not for large projects, good to teach
"verbose" is somewhat excessive. Of course, class declarations are a bit
more verbose and you don't have the nice property and indexer syntax. But
for the rest of it, Java is quite concise. We are still very far from

COBOL or even ADA.
forgetting about boxing?
Hashtable h = new Hashtable(); // maps strings to ints...
string s = "word";

c#:
h["word"]=(int)h["word"] + 1;

c# whidbey:
h["word"]++;

java:
h.setValue("word", newInteger(((Integer)h.getValue("word")).intValue( ) +
1)...) // if i got all the crap right...

C# - safe by default, more expressive, somewhat more to learn, somewhat more
concise, good for large projects, ok to teach

C++ - unsafe, most expressive, most to learn, very concise, good for

fooling
around with it (works for large projects if you are disciplined enough),
terrible to teach

Frankly I see C# as a combination of C++ and Delphi with some nasty C++
taken out and some "hot new" stuff put in.
My ideal for C# would be to allow everything that is safe!!!


To me, C# is what Java would have become if the Java guys had accepted

that Microsoft infuse its good ideas into it. J++ is the "missing link" between
Java and C#: Java + conditional compilation + delegates + P/Invoke
(J/Direct), etc.
So, I think that C# has more genes in common with Java than with C++.
Java is C++ with the nasty stuff taken out.
Don't quite agree.
I value C# as a language. For me it is Delphi++, and in fact the chief
language architect is the same.
I never liked J++... it added crap like pointers instead of "foreach",
delegates, etc...
P/Invoke is handy I agree.
For the C# vs. Java vs. C++, yes, I would say C# = Java++++, but Microsoft
does not like this statement.
Finally, Java is C++ with stuff taken out, but not necessarily nasty.
Even C# has some non-nasty stuff that is taken out...

The C++ heritage is just a marketing ploy to avoid nasty comments about
Microsoft copying Java.

Bruno

Nov 15 '05 #14

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:O4**************@TK2MSFTNGP12.phx.gbl...
Its more simplicity. It makes it easier to work with the language as a
whole.
Simpler for the people who write compilers, I agree.
Simpler for the people who use the language, this is more debatable.


it is not debatable -> it is more complex for people using the language.
it is an addition. if you don't want to use it, forget about it and don't
use it. so it is as "simple" as it was without it.
on the other hand, it is far more complex to fight with it if it is missing
and you want to use it.
see my example that started the thread... that crappy auxF function -> this
is the price you pay for not having the feature...
code bloat with stupid functions....

Bruno.

Nov 15 '05 #15
Kamen Yotov <ka***@yotov.org> wrote:

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:Oz****************@tk2msftngp13.phx.gbl...
Java - safe, least expressive, easiest to learn (simplest formal grammar), verbose, not for large projects, good to teach


"verbose" is somewhat excessive. Of course, class declarations are a bit
more verbose and you don't have the nice property and indexer syntax. But
for the rest of it, Java is quite concise. We are still very far from

COBOL
or even ADA.


forgetting about boxing?
Hashtable h = new Hashtable(); // maps strings to ints...
string s = "word";

c#:
h["word"]=(int)h["word"] + 1;

c# whidbey:
h["word"]++;

java:
h.setValue("word", newInteger(((Integer)h.getValue("word")).intValue( ) +
1)...) // if i got all the crap right...


If you're going to bring Whidbey into the equation, you should at least
also bring Java 1.5 in, which *does* have boxing.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #16

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:O4**************@TK2MSFTNGP12.phx.gbl...
Its more simplicity. It makes it easier to work with the language as a
whole.
Simpler for the people who write compilers, I agree.
Simpler for the people who use the language, this is more debatable.

To make things clear, I have no explicit problem with the feature, however
it will be something that will
1) make it more dificult to learn the language
2) make it harder to maintain code.
3) make it easier to screw up code
4) make it harder to realistically change the purpose of a distant object

For example, if 10 levels down one of your factories, which works wtih the
features added at level 9, but wants to return a type from level 3, your
class can't work. It adds a constraint, albeit a little one, that the
current system doesn't expose. Generics may well be a better solution.
Bruno.

Nov 15 '05 #17
<snip/>
To make things clear, I have no explicit problem with the feature, however
it will be something that will
1) make it more dificult to learn the language
Why? This feature does not add any new concept to the language, it just
relaxes typing rules that are somewhat stricter than they really need to be.
You don't need to even know about this feature when you start to learn the
language, and you are more likely to learn it "as you go", like lots of
other language features. And even if you had to learn everything to start
with, this feature would have a very small impact on the amount of what you
have to learn.
2) make it harder to maintain code.
I don't understand why at all. Can you elaborate?
3) make it easier to screw up code
Why again? It is completely safe. It does introduce any hole in the typing
system and the compiler can verify it just like the stricter rule. So, why
would it let you screw up code? On the other hand, it seems to me that being
able to state that CreateObject returns a DerivedObject rather than a
BaseObject in the DerivedFactory, and that GetFactory() returns a
DerivedFactory improves the typing of the API, gives additional
documentation to the person who reads the API. I only see gains in terms of
code quality.
4) make it harder to realistically change the purpose of a distant object
No, it imposes stricter contracts on the subclasses, and if your design is
correct, you should not run into situations where you narrow a return type
at level 9 but need to widen it again at level 10. This indicates a serious
anomaly, and I would rather have the compiler signal it than accept it
silently. Here, I always like to refer to B. Meyer's contracting metaphor:
"subclassing is subcontracting and, if you are an honest subcontractor and
accept a contract, you must be willing to do the job originally requested,
or more than the requested job, but no less."

For example, if 10 levels down one of your factories, which works wtih the
features added at level 9, but wants to return a type from level 3, your
class can't work. It adds a constraint, albeit a little one, that the
current system doesn't expose. Generics may well be a better solution.
Bruno.


Nov 15 '05 #18

"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:uP**************@TK2MSFTNGP12.phx.gbl...
<snip/>
To make things clear, I have no explicit problem with the feature, however it will be something that will
1) make it more dificult to learn the language
Why? This feature does not add any new concept to the language, it just
relaxes typing rules that are somewhat stricter than they really need to

be. You don't need to even know about this feature when you start to learn the
language, and you are more likely to learn it "as you go", like lots of
other language features. And even if you had to learn everything to start
with, this feature would have a very small impact on the amount of what you have to learn.
2) make it harder to maintain code.
I don't understand why at all. Can you elaborate?
3) make it easier to screw up code


Why again? It is completely safe. It does introduce any hole in the typing
system and the compiler can verify it just like the stricter rule. So, why
would it let you screw up code? On the other hand, it seems to me that

being able to state that CreateObject returns a DerivedObject rather than a
BaseObject in the DerivedFactory, and that GetFactory() returns a
DerivedFactory improves the typing of the API, gives additional
documentation to the person who reads the API. I only see gains in terms of code quality.

The three above are based on one thing. Outside of return values changing,
it is possible to do

MyObject o
MyObjectFactory MyObjectFactoryInstance;
o = MyObjectFactoryInstance.GetObject();
and Change MyObjectFactory to any lower object that supports GetObject, most
people are used to that.
With return values changing, changing the type of MyObjectFactoryInstance to
a less derived type could breaks code further in the method. While its a
simple and obvious result for people experienced in the langague and aware
of it, it could trip up maintainers and learners. Personally I think it'd be
easier to write a compiler for it than it would be to learn it after
learning C# without it.

Another issue is that it'd likely have to be CLS complaint or it is less
useful as a whole.
4) make it harder to realistically change the purpose of a distant object
No, it imposes stricter contracts on the subclasses, and if your design is
correct, you should not run into situations where you narrow a return type
at level 9 but need to widen it again at level 10. This indicates a serious anomaly, and I would rather have the compiler signal it than accept it
silently. Here, I always like to refer to B. Meyer's contracting metaphor:
"subclassing is subcontracting and, if you are an honest subcontractor and
accept a contract, you must be willing to do the job originally requested,
or more than the requested job, but no less."

While that works in factories and some other situations, the feature could
*easily* be abused to screw designs and break reusability. If you create a
fancy class that maintains an internal dictionary with alot of important
information, but use a derived return type on certain methods, that class
can only be used by derived types of your derived class, instead of by the
whole class. Granted that is a design decision and something you *shouldn't*
do, but I am not particularly convinced that its a pattern that people will
accept well.

Now, on other fronts, as I've said before I'm not entirely against this
feature(nor, for that matter, am I against return type overloading(with
proper syntax), although these two would either be mutually exclusive or
would require extended syntax), my issue is more that it is something that I
am concerned with as a matter of design. I don't know if the feature is
worth, especially in the face of generics, what its potential damage is.

For example, if 10 levels down one of your factories, which works wtih the features added at level 9, but wants to return a type from level 3, your
class can't work. It adds a constraint, albeit a little one, that the
current system doesn't expose. Generics may well be a better solution.
Bruno.



Nov 15 '05 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Eric Baker | last post by:
With this little snippet, i get an inconsistency between the behavior of string and dictionary class variables: Python 2.2.3 (#42, May 30 2003, 18:12:08) on win32 Type "copyright", "credits" or...
3
by: dayzman | last post by:
Hi, I've read somewhere that feature-based analysis can be used to extract the semantic structure of HTML documents. By semantic structure, they mean the model of the rendered view a reader...
7
by: Johann Blake | last post by:
If you had your wish and could have one (but only one) feature added to C#, what would you ask for? Second question. Same as the first question, but if the feature was for Visual Studio .NET.
30
by: Raymond Hettinger | last post by:
Proposal -------- I am gathering data to evaluate a request for an alternate version of itertools.izip() with a None fill-in feature like that for the built-in map() function: >>> map(None,...
12
by: Raymond Hettinger | last post by:
I am evaluating a request for an alternate version of itertools.izip() that has a None fill-in feature like the built-in map function: >>> map(None, 'abc', '12345') # demonstrate map's None...
32
by: toolmaster | last post by:
Since many of the modern computer languages have built-in namespace features, I can't understand why not add this feature into standard C. I've heard many people complain of the lacking of...
22
by: Luke Matuszewski | last post by:
We all know that feature detection technique works from very beggining of user-agents supporting JavaScript. We can alway check if eg. document has a write property or smth else: ...
4
by: ThunderMusic | last post by:
Hi, Is there a way we can send a feature request for Visual Studio? When using 'Refactor-->Encapsulate Field', I'd like to have an option for the references not to be updated anywhere in the...
10
by: Conrad Lender | last post by:
In a recent thread in this group, I said that in some cases object detection and feature tests weren't sufficient in the development of cross-browser applications, and that there were situations...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.