overload operator<<

  • Thread starter Thread starter Steve Richter
  • Start date Start date
Steve Richter said:
placing the emphasis on names to indicate what a statement does has two
problems. There is the obvious that if you dont know english the
meaning will not be apparent. ( yeah, yeah - keep the name simple and
consistent ). Another major problem is the designers of the .net
framework might make confusing choices.

I think there are few choices as confusing as making a bitshifting
operator effectively stream data, personally. That was a bad choice on
the part of C++ library designers.
on friday I had to deal with converting strings to and from ebcdic
bytes. I am still new to .net and had not yet worked with the Encoding
and Decoding classes. ( still dont know the difference between an
Encoder and Encoding ).

The difference is basically that an Encoding is stateless, and an
Encoder/Decoder has state. For instance, if you are trying to read
characters from a stream, you might only get part of a character, if
you're reading a multi-byte character and only get the start of it. A
Decoder remembers the bytes which have been read but haven't formed a
full character yet, so that when the rest of the bytes turn up, the
whole character can be returned.
I gave the MSDN documention 15 minutes and
none of the method names made sense to me. Without the examples I
found in google groups ( I think it was a post of Jon Skeets that was
the best example I found ), I would still be at it.

Here is the code that translate a string to ebcdic bytes:
System.Text.Encoding encoding =
System.Text.Encoding.GetEncoding( 37 ) ;
byte[] bytes = encoding.GetBytes( InString ) ;

"GetBytes" makes little sense to me. "TranslateTo" is more intuitive.
But why rely on either. In my c++ class framework masterpiece the code
reads:

EbcdicBytes bytes( 37 ) ; // code page 37
std::string InString ;
bytes = InString ; // replace the contents of bytes with InString
bytes << InString ; // add InString to the contents of bytes

I think this second example is much more readable. That is just my
opinion. What I dont agree with is the C# designers not allowing the
choice between the two styles. I prefer symbols over words.

You find the above more readable, but I suggest that if you could write
the above in C#, pretty much *anyone* who hadn't used C++ but had read
the C# language specification would disagree - they'd wonder how on
earth you were expecting to shift something by a string.

The << and >> operators have a well-specified meaning, which has
nothing to do with streaming data. Language allows one to be much more
descriptive than symbols - symbols are just a shorter way of expressing
things *when everyone knows what the symbols mean*. As soon as you
start changing what the symbols mean, confusion enters.

I'm very glad that I'll never have to read code like the above in C#.
 
Hi Jon,

Your reaction about confusing symbols is understandable I think, what
I dont understand is the hidden agressive part. In my experience with
c++ I have had never any problem with the overloaded meaning of
operator << and >>.
Like most truths in a human world its overloaded with respect to some
context. I dont understand why your c# spec is the wholy grail when
compaired to a completely vendor independent c++ language spec and
comite.

Rick

Steve Richter said:
placing the emphasis on names to indicate what a statement does has two
problems. There is the obvious that if you dont know english the
meaning will not be apparent. ( yeah, yeah - keep the name simple and
consistent ). Another major problem is the designers of the .net
framework might make confusing choices.

I think there are few choices as confusing as making a bitshifting
operator effectively stream data, personally. That was a bad choice on
the part of C++ library designers.
on friday I had to deal with converting strings to and from ebcdic
bytes. I am still new to .net and had not yet worked with the Encoding
and Decoding classes. ( still dont know the difference between an
Encoder and Encoding ).

The difference is basically that an Encoding is stateless, and an
Encoder/Decoder has state. For instance, if you are trying to read
characters from a stream, you might only get part of a character, if
you're reading a multi-byte character and only get the start of it. A
Decoder remembers the bytes which have been read but haven't formed a
full character yet, so that when the rest of the bytes turn up, the
whole character can be returned.
I gave the MSDN documention 15 minutes and
none of the method names made sense to me. Without the examples I
found in google groups ( I think it was a post of Jon Skeets that was
the best example I found ), I would still be at it.

Here is the code that translate a string to ebcdic bytes:
System.Text.Encoding encoding =
System.Text.Encoding.GetEncoding( 37 ) ;
byte[] bytes = encoding.GetBytes( InString ) ;

"GetBytes" makes little sense to me. "TranslateTo" is more intuitive.
But why rely on either. In my c++ class framework masterpiece the code
reads:

EbcdicBytes bytes( 37 ) ; // code page 37
std::string InString ;
bytes = InString ; // replace the contents of bytes with InString
bytes << InString ; // add InString to the contents of bytes

I think this second example is much more readable. That is just my
opinion. What I dont agree with is the C# designers not allowing the
choice between the two styles. I prefer symbols over words.

You find the above more readable, but I suggest that if you could write
the above in C#, pretty much *anyone* who hadn't used C++ but had read
the C# language specification would disagree - they'd wonder how on
earth you were expecting to shift something by a string.

The << and >> operators have a well-specified meaning, which has
nothing to do with streaming data. Language allows one to be much more
descriptive than symbols - symbols are just a shorter way of expressing
things *when everyone knows what the symbols mean*. As soon as you
start changing what the symbols mean, confusion enters.
 
Rick Elbers said:
Your reaction about confusing symbols is understandable I think, what
I dont understand is the hidden agressive part. In my experience with
c++ I have had never any problem with the overloaded meaning of
operator << and >>.

I guess I am a bit overzealous about it, just because readability is
such a big issue for me - and when symbols don't have clearly defined
meanings, readability goes down.

I dare say it's hard to remember, but do you know what your reaction
was the *first* time you saw the bitshifting operators being used for
something other than bitshifting.

Suppose someone didn't follow the accepted naming conventions for the
environment they're working on. It's not an immediate *problem* as such
- it doesn't make things completely unreadable - but it just makes
everything that *little* bit harder.
Like most truths in a human world its overloaded with respect to some
context. I dont understand why your c# spec is the wholy grail when
compaired to a completely vendor independent c++ language spec and
comite.

There are certainly things wrong with C# too - but I think it was the
right decision to keep bitshifting operators as just that. There are
many ways in which C++ is a real pig to read, IMO, and I think C# has
improved things significantly on that front. One of the contributing
factors to that is the restrictions on what can be overloaded where.
 
Jon said:
I think there are few choices as confusing as making a bitshifting
operator effectively stream data, personally. That was a bad choice on
the part of C++ library designers.

I have written a lot of programs. the only time I have ever used bit
shift is in c and c++ for some low level functions. ( and even then it
is an unclear operator. where do the carry out bits go? are the carry
in bits set to zero or one or the carry bit from an ajacent factor?
better expressed as a function. )

an asp.net or win forms programmer is never going to use the bit shift
operator, so your assertion that the operator will be ambiguous does
not "carry"!
The difference is basically that an Encoding is stateless, and an
Encoder/Decoder has state. For instance, if you are trying to read
characters from a stream, you might only get part of a character, if
you're reading a multi-byte character and only get the start of it. A
Decoder remembers the bytes which have been read but haven't formed a
full character yet, so that when the rest of the bytes turn up, the
whole character can be returned.

implementation details coerced by the CLI that illustrate the problems
with the do it all one way approach. A stateless operation is best
expressed as a standalone function defined in a namespace. The whole
reliance on static methods thing is something the programmer can become
accustomed to. I dont see the sense in claiming that the never used
bit shift operator has to remain unambiguous while at the same time
..NET makes heavy use of very ambiguous static and instance class
methods.

C# code would be easier to read if namespaces could contain standalone
functions.

-Steve
 
Steve Richter said:
I have written a lot of programs. the only time I have ever used bit
shift is in c and c++ for some low level functions. ( and even then it
is an unclear operator. where do the carry out bits go? are the carry
in bits set to zero or one or the carry bit from an ajacent factor?
better expressed as a function. )

an asp.net or win forms programmer is never going to use the bit shift
operator, so your assertion that the operator will be ambiguous does
not "carry"!

It's not a case of ambiguity so much as plain confusion. A C#
programmer who sees a shift operator being used for something other
than shifting is likely to
implementation details coerced by the CLI that illustrate the problems
with the do it all one way approach.

They're not implementation details - they're part of the documented
interface. I don't see why it's a bad thing to have an object which can
be used safely in multiple threads with no locking, and a separate
object which carries state and should therefore be used more carefully.
They're very closely related, of course, but they do perform slightly
different roles.

I can't see how being able to have standalone functions would help
there at all.
A stateless operation is best expressed as a standalone function
defined in a namespace.

There we'll have to disagree - do you think it's inconceivable that two
functions which perform different operations but have the same name
would be in the same namespace? How about int.Parse and double.Parse,
for instance? I don't see what's wrong with those being static methods.

Mind you, the Encoding methods aren't static anyway. Describing an
Encoding as stateless was slightly wrong - they're immutable, but can
carry state such as whether or not to use a preamble. Of course, they
also have properties which may or may not vary between two different
instances, depending on the implementation.
The whole reliance on static methods thing is something the
programmer can become accustomed to. I dont see the sense in claiming
that the never used bit shift operator has to remain unambiguous
while at the same time .NET makes heavy use of very ambiguous static
and instance class methods.

I don't see anything ambiguous about the method names - there are no
predefined names in the specification, so you can't assume that a
method has anything to do with the specified behaviour. That isn't true
for operators.

(Actually, there are a very few predefined method names in the
specification, to do with Dispose and Monitor.Enter/Exit, but I don't
think they're particularly relevant to the point in question.)
C# code would be easier to read if namespaces could contain standalone
functions.

I'm afraid we'll have to disagree.
 
Jon Skeet said:
It's not a case of ambiguity so much as plain confusion. A C#
programmer who sees a shift operator being used for something other
than shifting is likely to

Sorry - I didn't finish that bit, clearly.

It should be continued:

.... is likely to get confused or make invalid assumptions about what's
actually going on. It doesn't matter whether it's in ASP.NET, a console
app, a web service or Windows Forms, << and >> are shift operators.
That's how they're defined, and it's reasonable for people to expect
that to be how they're used.
 
Back
Top