more about the using statement

T

Tony Johansson

Hello!

I just wonder what is the point of having the reader variable declared as
TextReader in the snippet below..
Is it because of using the polymorfism on the reader variable perhaps.

using (TextReader reader = new StreamReader(fullPathname))
{
string line;
while ((line = reader.ReadLine()) != null)
{
source.Text += line + "\n";
}
}

//Tony
 
P

Peter Duniho

Hello!

I just wonder what is the point of having the reader variable declared as
TextReader in the snippet below..
Is it because of using the polymorfism on the reader variable perhaps.

In the example you give, there's really not any difference. The reference
only ever is stored in one variable, and that variable could just as
easily have been a StreamReader.

But since StreamReader and StringReader simply implement the abstract
TextReader class without adding anything new, it's nice to use them as
TextReaders. The same thing would apply to any other class someone might
derive from TextReader. That way the code is more general-purpose and
doesn't depend on a specific implementation of TextReader. Of course,
usually this would be a matter of passing the local variable to some
method that takes a TextReader, and of course that can be done whether or
not the variable is declared explicitly as just a TextReader versus a
StreamReader.

Obviously at some point you need to be explicit about which class is
created, but this only needs to be done in one specific place and the rest
of the code can be more reusable by using TextReader instead.

To some extent, declaring the local variable as a TextReader just makes it
that much more clear that the code within the using statement isn't
dependent at all on the reader being a StreamReader. Here, it's likely an
issue of code readability as anything else.

Pete
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

In that sentence using as another meaning, it basically do two things, first
it create a scope for the variable reader and second and more importantly it
call Dispose at the end of the scope.
In this construction you do not have to close the Reader. as the Dispose
method will do it for you, even if an exception is throw inside the scope.

Of course the variable being "used" must implement IDisposable
 
S

Scott M.

A StreamReader is a "type" of TextReader and that's why the code works. If
you ask me for fruit and I pass you an apple, it is ok, because an apple is
a "type" of fruit. This isn't quite polymorphism at work here, but simple
inheritance concepts.

Having said that, since a StreamReader is a more specific "type" than a
TextReader, you probably wouldn't want to keep this line of code as it is.
You'd want to declare reader as a StreamReader so that you can take full
advantage of a StreamReader's members in the using block. As it is now,
you'd only be able to use the more generic members of a TextReader in the
using block even though you really do have a StreamReader in memory.

-Scott
 
J

Jon Skeet [C# MVP]

Scott M. said:
A StreamReader is a "type" of TextReader and that's why the code works. If
you ask me for fruit and I pass you an apple, it is ok, because an apple is
a "type" of fruit. This isn't quite polymorphism at work here, but simple
inheritance concepts.

Having said that, since a StreamReader is a more specific "type" than a
TextReader, you probably wouldn't want to keep this line of code as it is.
You'd want to declare reader as a StreamReader so that you can take full
advantage of a StreamReader's members in the using block. As it is now,
you'd only be able to use the more generic members of a TextReader in the
using block even though you really do have a StreamReader in memory.

I prefer to only declare variables as the minimally specific type that
I need them to be. That makes it obvious that if you need to change the
implementation that happens to be used at a later date, it's okay to do
so.

In other words, I think the code is absolutely fine as it is :)
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,




Jon Skeet said:
I prefer to only declare variables as the minimally specific type that
I need them to be. That makes it obvious that if you need to change the
implementation that happens to be used at a later date, it's okay to do
so.

In other words, I think the code is absolutely fine as it is :)


I totally agree with you, there is nothing wrong with that code . Not only
that but I wish that ALL the code were always written like that. I have
found a lot of places where objects that implement IDisposables are nt being
used like tht and are not being disposed after use.
 
M

matthew-andrews

Hi,





I totally agree with you, there is nothing wrong with that code . Not only
that but I wish that ALL the code were always written like that. I have
found a lot of places where objects that implement IDisposables are nt being
used like tht and are not being disposed after use.


Nothing wrong with the code...

good use of the using statement - I always try to use the using
statement on any object which implements IDispose - but surely the
StringBuilder object should be employed instead of the string
concatination within a loop!!
 
J

Jon Skeet [C# MVP]

Nothing wrong with the code...

good use of the using statement - I always try to use the using
statement on any object which implements IDispose - but surely the
StringBuilder object should be employed instead of the string
concatination within a loop!!

Oh absolutely. My mistake for not being clearer - I was only commenting
on the declaration of the variable as a TextReader.
 
T

Tony Johansson

Hello!

Because the TextReader is an abstract class it mean that some method in the
TextReader class does not have an implementation. A wonder which method in
the TextReader class does not have an implementation which mean that the
method implemention must be done in the derived class in this case the
StreamReader class.

//Tony
 
P

Peter Duniho

Hello!

Because the TextReader is an abstract class it mean that some method in
the
TextReader class does not have an implementation. A wonder which method
in
the TextReader class does not have an implementation which mean that the
method implemention must be done in the derived class in this case the
StreamReader class.

Is that a question? If so, you may want to rephrase it. Possibly
including a question mark, to make it clear where the question is. I have
no idea what, if any, response might be expected with respect to the above.

Pete
 
J

Jon Skeet [C# MVP]

Peter Duniho said:
Is that a question? If so, you may want to rephrase it. Possibly
including a question mark, to make it clear where the question is. I have
no idea what, if any, response might be expected with respect to the above.

I should point out, however, that a class being abstract *doesn't* mean
that some methods aren't implemented. You can have an abstract class
without any abstract members.
 
P

Peter Duniho

So, would you declare a new textbox as a control?

I can't speak for Jon, but if Control was the minimally specific type I
needed the variable to be, then yes. I would.

Of course, ordinarily if you've got a TextBox instance, you are interested
in doing TextBox-like things with it. Like accessing the lines of the
text, or modifying or looking at the selection, or similar. In that case,
Control is not a minimally specific type needed for the variable and
should not be declared that way. You'd want to declare it with the full
type.

But sure...if all you ever do is get or set the Text property of the
TextBox, why not just declare it as a Control? (The VS Designer's default
behavior notwithstanding, of course).

Pete
 
S

Scott M.

But sure...if all you ever do is get or set the Text property of the
TextBox, why not just declare it as a Control? (The VS Designer's default
behavior notwithstanding, of course).

Because it limits me from using the control as it really is stored in memory
without a cast involved. Sure, I understand the potential benefits of what
you describe, but for me, I do that as the exception (no .NET pun intended),
not the rule. In the SreamReader/TextReader code that the OP shows, I can
understand it, considering that the TextReader is an abstract class. I can
also fully understand the benefits of using the minimally specific type or
interfaces when declaring method parameters (polymorphism). I just don't
agree that this is the best practice to follow as a rule for object
variables.
 
P

Peter Duniho

Because it limits me from using the control as it really is stored in
memory
without a cast involved.

???

Um. If (using the Control/TextBox example) Control is the minimally
specific type that you need the variable to be, then the fact that "it
limits you" is not a problem. Conversely, if the fact that "it limits
you" is a problem, then by definition Control would _not_ be the minimally
specific type that you need the variable to be.

You've set up a nice straw man, but otherwise I fail to see your point.
[...] I just don't
agree that this is the best practice to follow as a rule for object
variables.

No one is suggesting that you always use a base class type for your
variables instead of the actual type of the instance. In most cases, you
have a reason for creating an instance of a specific type and you would
want the full type as your variable type.

You've already acknowledged that in the example code, using TextReader
instead of StreamReader for the variable type is fine. And for the same
reason that that's fine, as a general rule if you don't care about the
more-derived type of the object instance, it's also fine to declare other
variables following the same pattern. Furthermore, doing so enhances
maintainability and reuse of the code you've written, because the code is
not unnecessarily constrained to being used with a more specific type than
it really needs.

Frankly, if you'd objected to the use of TextReader as the variable type
in the example code, I could at least see your argument as being
consistent, even if I don't agree with it. But as it is, you seem to be
making an argument just for the sake of being argumentative. I really
don't see the point in that.

Pete
 
S

Scott M.

Peter Duniho said:
???

Um. If (using the Control/TextBox example) Control is the minimally
specific type that you need the variable to be, then the fact that "it
limits you" is not a problem. Conversely, if the fact that "it limits
you" is a problem, then by definition Control would _not_ be the minimally
specific type that you need the variable to be.

Under that train of thought, why would you be making a Textbox in the first
place. Wouldn't you just declare a control variable to hold a reference to
a control on the heap? If a control is the minimally specific type, then
just make a control instance.
You've set up a nice straw man, but otherwise I fail to see your point.
[...] I just don't
agree that this is the best practice to follow as a rule for object
variables.

No one is suggesting that you always use a base class type for your
variables instead of the actual type of the instance. In most cases, you
have a reason for creating an instance of a specific type and you would
want the full type as your variable type.

You've already acknowledged that in the example code, using TextReader
instead of StreamReader for the variable type is fine. And for the same
reason that that's fine, as a general rule if you don't care about the
more-derived type of the object instance, it's also fine to declare other
variables following the same pattern. Furthermore, doing so enhances
maintainability and reuse of the code you've written, because the code is
not unnecessarily constrained to being used with a more specific type than
it really needs.

Frankly, if you'd objected to the use of TextReader as the variable type
in the example code, I could at least see your argument as being
consistent, even if I don't agree with it. But as it is, you seem to be
making an argument just for the sake of being argumentative. I really
don't see the point in that.

I'm not sure where you think I'm being argumentative, since I don't consider
this an argument. I'm simply telling you what my opinion is about what to
do as a general rule. As you've said yourself above, "In most cases, you
have a reason for creating an instance of a specific type and you would want
the full type as your variable type.". I agree and that is the simple point
I was trying to make.
 
P

Peter Duniho

Under that train of thought, why would you be making a Textbox in the
first
place.

I don't understand that question. You'd make a TextBox for the same
reason you'd ever make one: you want a control that would allow a user to
enter or otherwise interact with some text.
Wouldn't you just declare a control variable to hold a reference to
a control on the heap? If a control is the minimally specific type, then
just make a control instance.

How does that allow the user to use a TextBox?

You have to create a TextBox for the user to use it. Creating a Control
instance isn't sufficient.
I'm not sure where you think I'm being argumentative, since I don't
consider
this an argument. I'm simply telling you what my opinion is about what
to do as a general rule.

Inasmuch as your opinion conflicts with Jon's and/or mine, you are being
argumentative.
As you've said yourself above, "In most cases, you
have a reason for creating an instance of a specific type and you would
want
the full type as your variable type.". I agree and that is the simple
point
I was trying to make.

Then why didn't you say that instead of questioning the statement "I
prefer to only declare variables as the minimally specific type that I
need them to be"? Why would you question that statement if you don't have
a point that contradicts it?

Pete
 
S

Scott M.

Inasmuch as your opinion conflicts with Jon's and/or mine, you are being
argumentative.

Oh, well I guess using that logic I could say you are being argumentative to
me. And, anytime an opinion conflicts with others, thier is an argument.
Then why didn't you say that instead of questioning the statement "I
prefer to only declare variables as the minimally specific type that I
need them to be"? Why would you question that statement if you don't have
a point that contradicts it?

I'm pretty sure I did say that and I'm also pretty sure that you've been the
one taking the argumentative stand.
 
P

Peter Duniho

Oh, well I guess using that logic I could say you are being
argumentative to
me. And, anytime an opinion conflicts with others, thier is an argument.

That's true. It may not be a vehement argument, but there's not any
question in my mind that there's an argument. The dictionary definition
of the word "argument" agrees with this viewpoint.
I'm pretty sure I did say that and I'm also pretty sure that you've been
the
one taking the argumentative stand.

We are both being argumentative. The difference is that I've stated
reasons for my position. I'm not just being argumentative for the sake of
being argumentative. I have an actual point that I am supporting.

You, on the other hand, have questioned a statement and then not only
refused to provide any justification for questioning that statement, have
decided that you agree with it after all. Without admitting that you have
(i.e. continuing to be argumentative). In other words, you insist on
disagreeing (i.e. being argumentative) without having an actual
disagreement (i.e. apparently just for the sake of being argumentative).

I have no idea. Maybe you have some _other_ reason for being
argumentative. It's obviously not because you disagree with the
philosophy Jon proposed or that I paraphrased and agreed with. You
apparently agree with the philosophy. You are, if I understand correctly,
claiming that it's not just for the sake of being argumentative. I don't
really know what's left as a reason to be argumentative, but I'm all ears
if you want to explain some other reason for arguing about something you
don't disagree with.

Pete
 
J

Jon Skeet [C# MVP]

Scott M. said:
So, would you declare a new textbox as a control?

As Peter suggested, *if* I only needed to use members declared on
Control, then yes I would.

Your argument of "that stops me from using members declared only on
TextBox" immediately moves us away from the initial premise, so isn't
relevant. While the premise holds, take the suggested course of action.
When it doesn't hold, don't.
 

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