Framework functions - 'object' typed parameters too weak?

  • Thread starter Thread starter emma middlebrook
  • Start date Start date
E

emma middlebrook

Hello all

Here's the prototype for a System.Convert method.

public static int ToInt32(object value);

The documentation states that the parameter 'value' is an Object that
implements the IConvertible interface. It adds that an exception
InvalidCastException is thrown if 'value' does not implement that
interface.

Isn't this odd? Why doesn't the function take an IConvertible
reference? Wouldn't that strengthen the function's contract as this is
what is surely uses and requires?

Thanks for any clarification

Emma Middlebrook
(e-mail address removed)
 
you're right, it would be better...

the only method in the Convert class that should accept an object is
ToString(object value), since it doesn't need a IConvertible...
perhaps they wanted all the method to accept the same kind of arguments ???

anyway it's strange ...
 
Ron Bullman said:
Shortly, redundant code.

(From Encarta Dictionary (US English) bloat is defined as excessive increase
[an excessive amount or excessive increase in something])

In this particular case consider situation hundreds of callers calling
Convert and each explicitly casting, instead of doing that inside the
Convert.

Why would they need to cast though? How often does the caller actually
not know the type of the parameter? Why is your argument valid for this
example but not for all the other methods in the framework?
 
Jon,

Aha, semantics! Perhaps I misunderstod the OP's original intention, but is
it totally wrong to interpret that "take an IConvertible reference" means
casting? If so, then clearly my answer is not valid ;-(. (It also means then
that I have misunderstod "Wouldn't that strengthen the function's contract"
to imply the contract between programmer and code, but not the contract
between code and compiler. Still thinking too much C like, where you were
heavily depend also on the contract between programmer and code. How creat
the C# is indeed ;-).

But it still remains open why it's implemented as object instead of
IConvertible. Yes, if its IConvertible, then it will "improve compile-time
safety", but why implemented as object? Perhaps it's finally time for me to
download the SSCLI and study that more carefully.


Ron
 
Ron Bullman said:
Aha, semantics! Perhaps I misunderstod the OP's original intention, but is
it totally wrong to interpret that "take an IConvertible reference" means
casting?

Yes, in my opinion. He was proposing (as I understood it) that the
method signature be changed from:

public static int ToInt32(object value);
to
public static int ToInt32(IConvertible value);

That certainly wouldn't always involve casting on the caller's side.
If so, then clearly my answer is not valid ;-(. (It also means then
that I have misunderstod "Wouldn't that strengthen the function's contract"
to imply the contract between programmer and code, but not the contract
between code and compiler.
Right.

Still thinking too much C like, where you were
heavily depend also on the contract between programmer and code. How creat
the C# is indeed ;-).
:)

But it still remains open why it's implemented as object instead of
IConvertible. Yes, if its IConvertible, then it will "improve compile-time
safety", but why implemented as object? Perhaps it's finally time for me to
download the SSCLI and study that more carefully.

Well, from my copy of Rotor:

public static int ToInt32(object value) {
return value == null? 0: ((IConvertible)value).ToInt32(null);
}

So basically changing it to take IConvertible would be trivial.

My guess is that it was a design mistake in the framework. It's not the
only one, and it's not surprising. I really can't see any good reason
for it being as it is...
 
Jay B. Harlow said:
Jon,
I suspect changing the signature to:


Would be a mistake because of the System.Data library.

As well as any other framework function that relies on IConvertible would
then need to encapsulate the cast. ArrayList.ToArray? ICollection.CopyTo?
Granted for functions inside the framework this is not as big deal, as for
functions that I may be using heavily.

Given an array of Objects, I can call Convert.To* on any item in the array.
Whereas if the signature was changed then I need to do the cast to
IConvertible. Seeing System.Data.DataRow has an array of Object for the
values (the index/item property), I can call Convert.To* as is, such as:

Dim dr As DataRow

w = Convert.ToInt32(dr.Item(0))
x = Convert.ToString(dr.Item(1))
y = Convert.ToBoolean(dr(2))
z = Convert.ToDouble(dr(3))

Without needing to have a bunch of casts to IConvertible in the above.


So in the long run, IConvertible value may appear to make sense, I think it
would be the 'design mistake'.

Jay

I don't understand. The implementation of ToInt32 involves a cast to
IConvertible *internally* in order to do any useful work so the
method's parameter is too weakly typed *according to the
implementation*. Is this fact actually debatable?

I don't understand the example you give: your calling To* methods
code. What does this example show? You know a priori the format in
which you intend to convert your data row column values because you're
calling particular methods and so you know those methods' signatures!
I don't think this presents an argument against my conjecture.

Hoping that you or someone can explain a little further for me.

Thanks

Emma Middlebrook
(e-mail address removed)
 
Emma,
I don't understand. The implementation of ToInt32 involves a cast to
IConvertible *internally* in order to do any useful work so the
method's parameter is too weakly typed *according to the
implementation*. Is this fact actually debatable?
I am not debating that. What I am debating is the suggestion that it was a
design mistake.
I don't understand the example you give: your calling To* methods
code. What does this example show? You know a priori the format in
which you intend to convert your data row column values because you're
calling particular methods and so you know those methods' signatures!

System.Data.DataRow.Item returns an Object.

Convert.ToInt32 accepts an Object.

The call Convert.ToInt32(dataRow.item(0)) would be calling
Convert.ToInt32(Object obj).

If Convert.ToInt32(Object obj) changed to be Convert.ToInt32(IConvertible
obj) which I agree is more semantically correct:

Convert.ToInt32(dataRow.item(0))

Would receive a compile error, unless I added the cast to IConvertible,
which would again be more semantically correct. However the amount of code I
need to write, just 'doubled', a wrapper function would be called for. I
would probably wrap the entire Convert class. Those wrappers are currently
embedded inside of Convert.ToInt32(Object obj).

The other options would be:
- To change DataRow.Item to be IConvertible instead of Object. Then what
about the case where DataRow is returning an IStream or an Image or some
other class where IConvertible does not make sense?
- To change DataRow to have type safe methods similar to DataReader, which
then looses the benefits of being an indexer.
I don't think this presents an argument against my conjecture.
I know. ;-) In that you are convinced that it needs to be IConvertible, from
a semantically point of view, I agree. However! I am trying to show that it
would cause extra coding when you attempt to apply the Convert class to
other classes in the Framework such as DataRow.

Hope this helps
Jay

emma middlebrook said:
"Jay B. Harlow [MVP - Outlook]" <[email protected]> wrote in
message news: said:
Jon,
I suspect changing the signature to:


Would be a mistake because of the System.Data library.

As well as any other framework function that relies on IConvertible would
then need to encapsulate the cast. ArrayList.ToArray? ICollection.CopyTo?
Granted for functions inside the framework this is not as big deal, as for
functions that I may be using heavily.

Given an array of Objects, I can call Convert.To* on any item in the array.
Whereas if the signature was changed then I need to do the cast to
IConvertible. Seeing System.Data.DataRow has an array of Object for the
values (the index/item property), I can call Convert.To* as is, such as:

Dim dr As DataRow

w = Convert.ToInt32(dr.Item(0))
x = Convert.ToString(dr.Item(1))
y = Convert.ToBoolean(dr(2))
z = Convert.ToDouble(dr(3))

Without needing to have a bunch of casts to IConvertible in the above.


So in the long run, IConvertible value may appear to make sense, I think it
would be the 'design mistake'.

Jay

I don't understand. The implementation of ToInt32 involves a cast to
IConvertible *internally* in order to do any useful work so the
method's parameter is too weakly typed *according to the
implementation*. Is this fact actually debatable?

I don't understand the example you give: your calling To* methods
code. What does this example show? You know a priori the format in
which you intend to convert your data row column values because you're
calling particular methods and so you know those methods' signatures!
I don't think this presents an argument against my conjecture.

Hoping that you or someone can explain a little further for me.

Thanks

Emma Middlebrook
(e-mail address removed)
 
Jay B. Harlow said:
The other options would be:
- To change DataRow.Item to be IConvertible instead of Object. Then what
about the case where DataRow is returning an IStream or an Image or some
other class where IConvertible does not make sense?
- To change DataRow to have type safe methods similar to DataReader, which
then looses the benefits of being an indexer.

Personally I think there should be a third option: another class which
has wrapper methods which call Convert with a cast, with Convert itself
only taking IConvertible. Now that the framework is in its current
state, it would be better to create a class which has methods taking
IConvertible, and make Convert internally call that after the cast.
That way people who *do* want compile-time safety can get it very
easily.
 
Jon,
Which was actually buried in my first suggestion:

Yes having TypeSafeConvert & NonTypeSafeConvert in the Framework may be the
cleanest implementation, but then we get into explaining why there are two
of them. :-)

I'm at least glad you understand what I am babbling about ;-)

I'm sure someone could come up with better names for TypeSafeConvert &
NonTypeSafeConvert ;-)

Jay
 
Back
Top