.NET Forum / Languages / C# / March 2008
unboxing problem
|
|
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
Free MagazinesGet 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 ...
|
|
|