Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / March 2008

Tip: Looking for answers? Try searching our database.

unboxing problem

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
tshad - 25 Mar 2008 22:42 GMT
I am trying to test if my object is a TextBox and I tried:

if (messageOut is TextBox)

But I get an error message:

The type or namespace name 'TextBox' could not be found (are you missing a
using directive or an assembly reference?)

What would I be missing?

Thanks,

Tom
Jon Skeet [C# MVP] - 25 Mar 2008 23:00 GMT
> I am trying to test if my object is a TextBox and I tried:
>
[quoted text clipped - 6 lines]
>
> What would I be missing?

A using directive or an assembly reference, as it suggests. Is this a
WinForms app or a web app? What using directives do you have at the top
of your file?

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

tshad - 26 Mar 2008 18:36 GMT
>> I am trying to test if my object is a TextBox and I tried:
>>
[quoted text clipped - 11 lines]
> WinForms app or a web app? What using directives do you have at the top
> of your file?

Found it.

Apparently, I needed the System.Windows.Forms as a using statement (which it
was) but I was missing the reference.

Thanks,

Tom
tshad - 25 Mar 2008 23:01 GMT
>I am trying to test if my object is a TextBox and I tried:
>
[quoted text clipped - 6 lines]
>
> What would I be missing?

What I am trying to do is take an object and write to that object.  The
object could be a TextBox, Label, String, etc.  The error message makes no
sense.  It knows about the TextBox type as I can do:

       public static void Write(TextBox messageOut,string text)
       {
           messageOut.Text += text;
       }

And this works fine.

I want to change it to something like:

       public static void Write(object messageOut,string text)
       {
           if (messageOut is TextBox)
           {
               (TextBox)message.Text += text;
           }
           if (messageOut is String)
           {
               (String)message += text;
           }
       }

Thanks,

Tom
Peter Duniho - 25 Mar 2008 23:16 GMT
> What I am trying to do is take an object and write to that object.  The
> object could be a TextBox, Label, String, etc.  The error message makes  
> no
> sense.

Well, it would have made sense if you'd shown us the lines of code causing  
it.  Instead, you showed us a line that most likely compiles just fine,  
given your follow-up post.

I believe the problem you're having is with these two:

>                 (TextBox)message.Text += text;

and:

>                 (String)message += text;

With the first, you can fix the error by casting correctly:

   ((TextBox)message).Text += text;

With the second, there is no correct line of code that is equivalent, as  
strings are immutable.

It _looks_ like you are trying to accomplish something along the lines of  
a TraceListener, TextWriter, etc.  If so, you should implement concrete  
versions of those classes that encapsulate the underlying behavior you  
want.  Then you would call the appropriate methods on those objects, which  
would then already know exactly how to modify the underlying object that  
should receive the new text.

Without knowing more about exactly what you're trying to do, it's hard to  
suggest something specific.

Pete
tshad - 26 Mar 2008 22:57 GMT
>> What I am trying to do is take an object and write to that object. The
>> object could be a TextBox, Label, String, etc.  The error
[quoted text clipped - 29 lines]
> Without knowing more about exactly what you're trying to do, it's
> hard to suggest something specific.

What I am doing is creating a Log class to allow me to write to different
type of objects (TextBoxes, Labels, Strings etc).  As another type comes up
I would just add it in.

In my example, I have one function (Write) that just adds a variable number
of strings to some object.  The first parameter will always be the object I
am writing to.

********************************************
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Text;

namespace RepositoryServiceApp.BusinessLayer
{
   public class Log
   {

       public static void Write(params object[] names)
       {
           object destination = null;

           foreach (object name in names)
           {
               if (destination == null)
               {
                   destination = name;
               }
               else
               {
                   if (name is string)
                   {
                       if (destination is TextBox)
                       {
                           ((TextBox)destination).Text += (string)name;
                       }
                       if (destination is Label)
                       {
                           ((Label)destination).Text += (string)name;
                       }
                       if (destination is string)
                       {
                           destination += (string)name;
                       }
                   }
               }
           }
       }
       public static void Write(object messageOut,string text)
       {
       }
   }
}

********************************************

Then I could call it like so, where Status could be a TextBox or a string):

               Log.Write(Status, parameter.ParameterName,"
",parameter.SqlDbType.ToString(),"    ",stemp,Environment.NewLine);

This seems to work pretty well.

I could also set up set a variable at the top of the program:

       static object statusOutput = null;

Then later in my code I could set statusOutput to what ever I wanted:
Status(TextBox), stemp (string), etc and call it like so:

               Log.Write(statusOutput, stext1,"       ",stext2,"
",stemp,Environment.NewLine);

This would allow me to use the same code to write status information to a
Multiline TextBox or a strint, or something else by just changing the
statusOutput at the top of the program.

Thanks,

Tom

> Pete
Peter Duniho - 26 Mar 2008 23:51 GMT
> What I am doing is creating a Log class to allow me to write to different
> type of objects (TextBoxes, Labels, Strings etc).  As another type comes  
> up
> I would just add it in.

Well, the usual way to do this is to create a specific concrete class  
inheriting a class like TraceListener or TextWriter, one for each kind of  
target class.  Then each concrete class would already have all the correct  
type information and you wouldn't need to cast anything.

An alternative might be to have a single class that requires the passing  
in of a delegate that takes as the parameter a string, and then which  
outputs that string to whatever is appropriate for the code creating an  
instance of the logging class using the delegate.  This is more general  
purpose and avoids having to create a new class for each possible output  
target type.  But it would mean you'd have to at least declare a delegate  
method for each possible output target type.

You can do it using the kind of code you've posted (except having fixed  
the problems, of course...even the new code you posted still has the  
problem that your code assumes strings are mutable when they aren't).  But  
I think it's a poor design choice to have an "if/else if" block testing  
the type and executing special code for each type.

At the very least, you need to fix the problem with the string as output,  
and you should really be using "if/else if" instead of repeated "if"  
statements.  It's not likely to cause a real performance problem the way  
it is, but it's unnecessarily wasteful anyway.

Pete
tshad - 27 Mar 2008 01:14 GMT
>> What I am doing is creating a Log class to allow me to write to
>> different type of objects (TextBoxes, Labels, Strings etc).  As
[quoted text clipped - 6 lines]
> all the correct type information and you wouldn't need to cast
> anything.

Not sure how I would do that or why if most of the time I am dealing only
with a string or textboxes and labels for this.  But I will be using other
objects later.

> An alternative might be to have a single class that requires the
> passing in of a delegate that takes as the parameter a string, and
[quoted text clipped - 9 lines]
> aren't).  But I think it's a poor design choice to have an "if/else
> if" block testing the type and executing special code for each type.

You're right, of course.

I tried it out with the string as so:

           string stemp = null;

           Log.Write(stemp, "a test", " to see", " if this", " would
work");
           Log.Write(stemp, " or not.", "  What do you", " think?");
           string stemp2 = stemp;

but stemp and stemp2 were both null at the end.

Textboxes and Labels work fine though.

I guess I  could return the object, but then I would have to cast it.  This
would nullify the point of doing it this way so that I can just define the
output as an object and then just pass in whatever type of object I want and
have the Write method handle the differences.  It works great for Textboxes
and Labels as I mentioned, but then there's that pesky string :(

Why is the if/else testing of the type a bad design - I agree that if/else
better than my multiple ifs.

> At the very least, you need to fix the problem with the string as
> output, and you should really be using "if/else if" instead of
> repeated "if" statements.  It's not likely to cause a real
> performance problem the way it is, but it's unnecessarily wasteful
> anyway.
I agree on that.

This was just the first pass.

I had thought about using a switch statement, but not sure if you can since
I am not testing a type and not a value.

Thanks,

Tom
> Pete
Peter Duniho - 27 Mar 2008 02:07 GMT
>> Well, the usual way to do this is to create a specific concrete class
>> inheriting a class like TraceListener or TextWriter, one for each
[quoted text clipped - 6 lines]
> other
> objects later.

IMHO, there are two significant benefits: one has to do with the design  
itself, and specifically that you isolate specific behaviors in specific  
classes.  One major focus of OOP is to avoid a single code entity that  
handles everything.  It's more maintainable for code to be simple and  
specialized.

The other benefit is relatively minor, but IMHO speaks to the elegance of  
following the OOP path.  That is, the code you posted will have to check  
the type of the target data structure every time you want to write  
something.  If you instead use a good OOP hierarchy with specialized  
target classes as your writers, this test doesn't happen.  The code that  
creates the target class instances decides at that point what the target  
type is (which it has to do anyway), and then for the rest of the lifetime  
of that code, the code just always knows what to do, no conditionals  
needed.

The real-world performance may be negligible, but it does highlight the  
inefficiency of the approach you've taken.  It seems to me that when  
something is simpler _and_ more performant, the choice is obvious.  After  
all, most of the time as programmers we find ourselves having to balance  
those two attributes, having to lessen one in order to increase the  
other.  It's not often we get to have our cake and eat it too, but when we  
do I think that that's the problem we're coding a solution for telling us  
very clearly to follow that design.

> I tried it out with the string as so:
>
[quoted text clipped - 6 lines]
>
> but stemp and stemp2 were both null at the end.

Yes, of course.  You are passing the strings by value, and since strings  
are immutable, the += operator cannot change the original string.  It has  
to create a new string, and so your string variable only gets modified  
within the Write() method, as the local copy of that reference used as the  
parameter for the method.

This could be fixed by making the parameter passed by reference, but it's  
fairly awkward to do that with a variable length parameter list  
(essentially what you wind up doing is not taking advantage of the  
variable length semantics at all, instead passing an actual array you can  
get at later, modifying the element of interest in the array inside the  
method, and then in the code that called the method, copying any new  
values back out of the array after calling the method).

IMHO, this is yet another reason that having specialized classes for each  
target object works better.  Each specialized class can easily encapsulate  
whatever logic is required in order to actually allows the target object  
to be updated.  In this case, your specialized class for the string would  
either have a string internally that it updates any time it's written to,  
or (if you follow the "single class that is given a delegate to write to  
the object" paradigm I mentioned earlier) the delegate method would itself  
know where the string is being stored and could update it.

> Textboxes and Labels work fine though.

Of course.  They are mutable, and so you can pass them by value to the  
Write() method and still have that method be able to change them.

> I guess I could return the object, but then I would have to cast it.

That would also eliminate your variable length parameter list, since you  
can only return one value.  If you were going to follow this path (and I  
don't recommend it), you might as well do what I described above and pass  
an explicitly-created object array, where you change the variable in situ  
and then copy the new value back out after calling the Write() method.

> This
> would nullify the point of doing it this way so that I can just define  
[quoted text clipped - 4 lines]
> Textboxes
> and Labels as I mentioned, but then there's that pesky string :(

IMHO, "that pesky string" is telling you something.  It's telling you that  
you're heading down the wrong path.

> Why is the if/else testing of the type a bad design - I agree that  
> if/else
> better than my multiple ifs.

See my comments at the top of this message.  Basically, you're putting too  
much information into the method.  It knows too much, tries to do too much.

Pete
Ben Voigt [C++ MVP] - 27 Mar 2008 15:03 GMT
>>> What I am trying to do is take an object and write to that object.
>>> The object could be a TextBox, Label, String, etc.  The error

As already mentioned, you can't write to strings.  You can't change strings
in any way.  Use a StringBuilder instead, which has an append method.
tshad - 25 Mar 2008 23:03 GMT
>I am trying to test if my object is a TextBox and I tried:
>
[quoted text clipped - 6 lines]
>
> What would I be missing?

I have my using clauses as:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Drawing;
using System.Text;
using System.IO;
using System.Collections;
using System.Windows.Forms;

Thanks,

Tom
Peter Duniho - 25 Mar 2008 23:07 GMT
> I am trying to test if my object is a TextBox and I tried:
>
[quoted text clipped - 7 lines]
>
> What would I be missing?

Well, as a first approximation, I'd guess: a using directive, an assembly  
reference, or possibly both.

If you have a concise-but-complete code sample that demonstrates the  
problem, something more specific might be offered.  Otherwise, no.

By the way, this is not an "unboxing problem".  TextBox isn't a value  
type, so it wouldn't ever be boxed in the first place.

Pete

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.