|
ms
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Implicit conversion design issuesvice versa. I have two classes, one Driver and one called StringWrapper. These are just test classes that try and emulate the pattern im trying to follow in an existing project. These are my steps: 1) I have a method "printMe" existing in the application which originally used to take in a string. This method is static and sits in the Driver class. I cannot remove this method since it public and is used all over the application. 2) Now, Ive realised that I need to do some parsing and cleaning up of the string before the method can continue to execute its logic (printMe). 3) My solution was to change the method sig to take in a StringWrapper class, created by me, that will take in an implicit string and return a StringWrapper object with the cleaned up string. 4) Now, when the StringWapper object is used by the code in the method printMe, I want to treat it as a String object and not a StringWrapper object. So what Ive done is create another implicit conversion from StringWrapper to String. I hope this makes sense at this point. Essentially Im tring to minimize code changes in the code that calls my printMe method so that it knows of only String objects. AND the reminaing logic in printMe function should only know of String objects as well. So the StringWrapper class will essentially convert string to an object of its type, do the cleaning of the string and then, whereever the StringWrapper instance is used in printMe method, it should expose itself as a String instead. So my question is 1) In my printMe method, I had a statement called Console.Write(val.ToLower()). This threw me an exception because it said the StringWrapper does not support the ToLower method. How come even though I have an implicit conversion? 2) If I do Console.Write(((string)val).ToLower()); it works!! Even though this is an explicit conversion and I havent defined any explicit conversions.... Im kinda lost here.... can anyone help me with a solution to this problem? Thanks, Girish Driver Class ------------- using System; namespace test1 { class Driver { //old func sig was; static public void printMe(String val) static public void printMe(StringWrapper val) { //Console.Write(val.ToLower()); //old Console.Write(((string)val).ToLower()); } [STAThread] static void Main(string[] args) { String b = "Testing 123"; Driver.printMe(b); //wait for input before exiting Console.Read(); } } } StringWrapper Class --------------------- using System; namespace test1 { public class StringWrapper { private String _val; public String val { get { return _val; } } public StringWrapper(String val) { this._val = val; } static public implicit operator StringWrapper(String val) { val += " (im changed)"; return new StringWrapper(val); } static public implicit operator string(StringWrapper val) { return val.val; } } } For those of you who thought I didnt attach any code, since ive wrote a long
email, you can find the code at the bottom of my earlier post. I know some people must be going... OK im reading all this stuff.. so wheres the code now??? Show quote :-):-):-):-) "Girish" <gba***@tietronixinc.com> wrote in message news:e%23NY7pNMFHA.3544@TK2MSFTNGP10.phx.gbl... > Im trying to understand implicit type conversions from object -> string > and vice versa. > > I have two classes, one Driver and one called StringWrapper. These are > just test classes that try and emulate the pattern im trying to follow in > an existing project. > > These are my steps: > 1) I have a method "printMe" existing in the application which originally > used to take in a string. This method is static and sits in the Driver > class. I cannot remove this method since it public and is used all over > the application. > 2) Now, Ive realised that I need to do some parsing and cleaning up of the > string before the method can continue to execute its logic (printMe). > 3) My solution was to change the method sig to take in a StringWrapper > class, created by me, that will take in an implicit string and return a > StringWrapper object with the cleaned up string. > 4) Now, when the StringWapper object is used by the code in the method > printMe, I want to treat it as a String object and not a StringWrapper > object. So what Ive done is create another implicit conversion from > StringWrapper to String. > > I hope this makes sense at this point. Essentially Im tring to minimize > code changes in the code that calls my printMe method so that it knows of > only String objects. AND the reminaing logic in printMe function should > only know of String objects as well. So the StringWrapper class will > essentially convert string to an object of its type, do the cleaning of > the string and then, whereever the StringWrapper instance is used in > printMe method, it should expose itself as a String instead. > > So my question is > 1) In my printMe method, I had a statement called > Console.Write(val.ToLower()). This threw me an exception because it said > the StringWrapper does not support the ToLower method. How come even > though I have an implicit conversion? > 2) If I do Console.Write(((string)val).ToLower()); it works!! Even though > this is an explicit conversion and I havent defined any explicit > conversions.... > > Im kinda lost here.... can anyone help me with a solution to this problem? > > Thanks, > Girish > > Driver Class > ------------- > using System; > namespace test1 { > class Driver { > //old func sig was; static public void printMe(String val) > static public void printMe(StringWrapper val) { > //Console.Write(val.ToLower()); //old > Console.Write(((string)val).ToLower()); > } > > [STAThread] > static void Main(string[] args) { > String b = "Testing 123"; > Driver.printMe(b); > > //wait for input before exiting > Console.Read(); > } > } > } > > > StringWrapper Class > --------------------- > using System; > namespace test1 { > public class StringWrapper { > private String _val; > > public String val { > get { return _val; } > } > > public StringWrapper(String val) { > this._val = val; > } > > static public implicit operator StringWrapper(String val) { > val += " (im changed)"; > return new StringWrapper(val); > } > > static public implicit operator string(StringWrapper val) { > return val.val; > } > } > } > > Oh ... Ok maybe this seems simple to me.. but I might miss something
application specfic.. if you are able to change the signature.. I assume you have the source code.. why can't you write the cleanup code as the first few lines of the printMe and make it simple? VJ Show quote "Girish" <gba***@tietronixinc.com> wrote in message news:%23E%23zSvNMFHA.2604@TK2MSFTNGP10.phx.gbl... > For those of you who thought I didnt attach any code, since ive wrote a > long email, you can find the code at the bottom of my earlier post. I know > some people must be going... OK im reading all this stuff.. so wheres the > code now??? > > :-):-):-):-) > > > "Girish" <gba***@tietronixinc.com> wrote in message > news:e%23NY7pNMFHA.3544@TK2MSFTNGP10.phx.gbl... >> Im trying to understand implicit type conversions from object -> string >> and vice versa. >> >> I have two classes, one Driver and one called StringWrapper. These are >> just test classes that try and emulate the pattern im trying to follow in >> an existing project. >> >> These are my steps: >> 1) I have a method "printMe" existing in the application which originally >> used to take in a string. This method is static and sits in the Driver >> class. I cannot remove this method since it public and is used all over >> the application. >> 2) Now, Ive realised that I need to do some parsing and cleaning up of >> the string before the method can continue to execute its logic (printMe). >> 3) My solution was to change the method sig to take in a StringWrapper >> class, created by me, that will take in an implicit string and return a >> StringWrapper object with the cleaned up string. >> 4) Now, when the StringWapper object is used by the code in the method >> printMe, I want to treat it as a String object and not a StringWrapper >> object. So what Ive done is create another implicit conversion from >> StringWrapper to String. >> >> I hope this makes sense at this point. Essentially Im tring to minimize >> code changes in the code that calls my printMe method so that it knows of >> only String objects. AND the reminaing logic in printMe function should >> only know of String objects as well. So the StringWrapper class will >> essentially convert string to an object of its type, do the cleaning of >> the string and then, whereever the StringWrapper instance is used in >> printMe method, it should expose itself as a String instead. >> >> So my question is >> 1) In my printMe method, I had a statement called >> Console.Write(val.ToLower()). This threw me an exception because it said >> the StringWrapper does not support the ToLower method. How come even >> though I have an implicit conversion? >> 2) If I do Console.Write(((string)val).ToLower()); it works!! Even though >> this is an explicit conversion and I havent defined any explicit >> conversions.... >> >> Im kinda lost here.... can anyone help me with a solution to this >> problem? >> >> Thanks, >> Girish >> >> Driver Class >> ------------- >> using System; >> namespace test1 { >> class Driver { >> //old func sig was; static public void printMe(String val) >> static public void printMe(StringWrapper val) { >> //Console.Write(val.ToLower()); //old >> Console.Write(((string)val).ToLower()); >> } >> >> [STAThread] >> static void Main(string[] args) { >> String b = "Testing 123"; >> Driver.printMe(b); >> >> //wait for input before exiting >> Console.Read(); >> } >> } >> } >> >> >> StringWrapper Class >> --------------------- >> using System; >> namespace test1 { >> public class StringWrapper { >> private String _val; >> >> public String val { >> get { return _val; } >> } >> >> public StringWrapper(String val) { >> this._val = val; >> } >> >> static public implicit operator StringWrapper(String val) { >> val += " (im changed)"; >> return new StringWrapper(val); >> } >> >> static public implicit operator string(StringWrapper val) { >> return val.val; >> } >> } >> } >> >> > > True, I could have. But for the future, I can just let everyone know, use
the StringWrapper class from now on people for your string manuplilation. This is easier than telling everyone, hey when you write a method in the future, remember to call this other helper function and make sure its called before any other code. I dont know, but i usually like to have more than one way of doing things and pick whats appropriate.... and if the implicit cast mehod is not the way to go... id really appreciate it if someone can help me understand why. :) thanks! Girish Show quote "VJ" <vijayba***@yahoo.com> wrote in message news:uBJIizOMFHA.3380@TK2MSFTNGP15.phx.gbl... > Oh ... Ok maybe this seems simple to me.. but I might miss something > application specfic.. if you are able to change the signature.. I assume > you have the source code.. why can't you write the cleanup code as the > first few lines of the printMe and make it simple? > > VJ > > "Girish" <gba***@tietronixinc.com> wrote in message > news:%23E%23zSvNMFHA.2604@TK2MSFTNGP10.phx.gbl... >> For those of you who thought I didnt attach any code, since ive wrote a >> long email, you can find the code at the bottom of my earlier post. I >> know some people must be going... OK im reading all this stuff.. so >> wheres the code now??? >> >> :-):-):-):-) >> >> >> "Girish" <gba***@tietronixinc.com> wrote in message >> news:e%23NY7pNMFHA.3544@TK2MSFTNGP10.phx.gbl... >>> Im trying to understand implicit type conversions from object -> string >>> and vice versa. >>> >>> I have two classes, one Driver and one called StringWrapper. These are >>> just test classes that try and emulate the pattern im trying to follow >>> in an existing project. >>> >>> These are my steps: >>> 1) I have a method "printMe" existing in the application which >>> originally used to take in a string. This method is static and sits in >>> the Driver class. I cannot remove this method since it public and is >>> used all over the application. >>> 2) Now, Ive realised that I need to do some parsing and cleaning up of >>> the string before the method can continue to execute its logic >>> (printMe). >>> 3) My solution was to change the method sig to take in a StringWrapper >>> class, created by me, that will take in an implicit string and return a >>> StringWrapper object with the cleaned up string. >>> 4) Now, when the StringWapper object is used by the code in the method >>> printMe, I want to treat it as a String object and not a StringWrapper >>> object. So what Ive done is create another implicit conversion from >>> StringWrapper to String. >>> >>> I hope this makes sense at this point. Essentially Im tring to minimize >>> code changes in the code that calls my printMe method so that it knows >>> of only String objects. AND the reminaing logic in printMe function >>> should only know of String objects as well. So the StringWrapper class >>> will essentially convert string to an object of its type, do the >>> cleaning of the string and then, whereever the StringWrapper instance is >>> used in printMe method, it should expose itself as a String instead. >>> >>> So my question is >>> 1) In my printMe method, I had a statement called >>> Console.Write(val.ToLower()). This threw me an exception because it said >>> the StringWrapper does not support the ToLower method. How come even >>> though I have an implicit conversion? >>> 2) If I do Console.Write(((string)val).ToLower()); it works!! Even >>> though this is an explicit conversion and I havent defined any explicit >>> conversions.... >>> >>> Im kinda lost here.... can anyone help me with a solution to this >>> problem? >>> >>> Thanks, >>> Girish >>> >>> Driver Class >>> ------------- >>> using System; >>> namespace test1 { >>> class Driver { >>> //old func sig was; static public void printMe(String val) >>> static public void printMe(StringWrapper val) { >>> //Console.Write(val.ToLower()); //old >>> Console.Write(((string)val).ToLower()); >>> } >>> >>> [STAThread] >>> static void Main(string[] args) { >>> String b = "Testing 123"; >>> Driver.printMe(b); >>> >>> //wait for input before exiting >>> Console.Read(); >>> } >>> } >>> } >>> >>> >>> StringWrapper Class >>> --------------------- >>> using System; >>> namespace test1 { >>> public class StringWrapper { >>> private String _val; >>> >>> public String val { >>> get { return _val; } >>> } >>> >>> public StringWrapper(String val) { >>> this._val = val; >>> } >>> >>> static public implicit operator StringWrapper(String val) { >>> val += " (im changed)"; >>> return new StringWrapper(val); >>> } >>> >>> static public implicit operator string(StringWrapper val) { >>> return val.val; >>> } >>> } >>> } >>> >>> >> >> > > > So my question is Implicit conversions are only applied in some circumstances, method > 1) In my printMe method, I had a statement called > Console.Write(val.ToLower()). This threw me an exception because it said > the StringWrapper does not support the ToLower method. How come even > though I have an implicit conversion? resolution is not one of them(atleast while resolving the method set the type has. Conversions for parameters are considered while dealing with overload resolution, but the type of the variable is static.) As far as the compiler is concerned, the only methods your type has are those it or its bases define. > 2) If I do Console.Write(((string)val).ToLower()); it works!! Even though By casting here you are telling the compiler you want to cause the > this is an explicit conversion and I havent defined any explicit > conversions.... > conversion. Since implicit conversions do not happen during method resolution, you have to explicitly tell the compiler to perform the conversion and to call string::ToLower(). Thanks for your reply Daniel. I have more qs, and maybe these are silly qs
but please bear with me. 1) Why does the compiler not complain that I dont have an explicit cast specified in my type? I know you cannot have both implicit and explicit defined but if im stating I need to envoke an explicit cast - it somehow "understands" i really mean execute the implicit cast method.. If the answer to this q is "well, thats the way it is...", i guess I can live with that. :-) 2) Do conversions of types only happen during overloading? What are the other circumstances? 3) I noticed that this pattern causes an infinite loop. Shouldnt the complier choke at this? static public implicit operator StringWrapper(String val) { val += " (im changed)"; //return new StringWrapper(val); return val; } g Show quote "Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in message news:Ou2fIaPMFHA.656@TK2MSFTNGP14.phx.gbl... >> So my question is >> 1) In my printMe method, I had a statement called >> Console.Write(val.ToLower()). This threw me an exception because it said >> the StringWrapper does not support the ToLower method. How come even >> though I have an implicit conversion? > > Implicit conversions are only applied in some circumstances, method > resolution is not one of them(atleast while resolving the method set the > type has. Conversions for parameters are considered while dealing with > overload resolution, but the type of the variable is static.) As far as > the compiler is concerned, the only methods your type has are those it or > its bases define. > >> 2) If I do Console.Write(((string)val).ToLower()); it works!! Even though >> this is an explicit conversion and I havent defined any explicit >> conversions.... >> > > By casting here you are telling the compiler you want to cause the > conversion. Since implicit conversions do not happen during method > resolution, you have to explicitly tell the compiler to perform the > conversion and to call string::ToLower(). > > > "Girish" <gba***@tietronixinc.com> wrote in message Its no problem. Conversions and overloading are the most confusing parts of news:%23D5BHxPMFHA.2420@TK2MSFTNGP12.phx.gbl... > Thanks for your reply Daniel. I have more qs, and maybe these are silly qs > but please bear with me. > the spec, atleast from a compiler writer's point of view. I don't mind trying to explain it. > 1) Why does the compiler not complain that I dont have an explicit cast Well, "thats the way it is" is pretty close to it, but its not complete, ;). > specified in my type? I know you cannot have both implicit and explicit > defined but if im stating I need to envoke an explicit cast - it somehow > "understands" i really mean execute the implicit cast method.. If the > answer to this q is "well, thats the way it is...", i guess I can live > with that. :-) Basically the rules are an explicit cconversion must be explicitly declared(using a cast operator), while an implicit cast may or may not be explicit. In my opinion this is done to allow for exactly what you are seeing here, that is permit the coder to explicitly tell the compiler to perform a conversion in a situation where implicit conversions are not in effect. > 2) Do conversions of types only happen during overloading? What are the Implicit conversions are possible during any assignment, return or parameter > other circumstances? pass operation(both of which you could consider an assignment and look like or are assignments in other languages). Overload resolution takes conversions in account to determine the proper overload, assignment takes it in account to determine if any conversion steps are required between the source and the target type, casting can obviously explicitly cause a conversion, a return statement can cause . I don't think there are any other circumstances where this happens, but I don't have the spec on hand to be sure(can't recall off hand if implicit conversions to bool are considered in if statements, for example). > 3) I noticed that this pattern causes an infinite loop. Shouldnt the The compiler should probably spit out a warning that you are going to enter > complier choke at this? > > static public implicit operator StringWrapper(String val) { > val += " (im changed)"; > //return new StringWrapper(val); > return val; > } > an infinite loop, but it *is* legal code. The reason for this is that the compiler cannot really tell that the infinite recursion is going to happen, just that its likely or possible. While its obvious to us, without being able to understand the method as a whole, the compiler could only guess as to if you actually meant to cause recursion or not. Thus it is something it should probably warn about, but not emit an error. Thansk for helping me out Daniel. I bet if you had a buck for every thank
you expressed by a person you helped, Im sure youd be real rich!!!! if your not already tho.. ;-) Thanks a million for what its worth. :-) girish Show quote "Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in message news:OfCf28PMFHA.3076@TK2MSFTNGP14.phx.gbl... > > "Girish" <gba***@tietronixinc.com> wrote in message > news:%23D5BHxPMFHA.2420@TK2MSFTNGP12.phx.gbl... >> Thanks for your reply Daniel. I have more qs, and maybe these are silly >> qs but please bear with me. >> > > Its no problem. Conversions and overloading are the most confusing parts > of the spec, atleast from a compiler writer's point of view. I don't mind > trying to explain it. > >> 1) Why does the compiler not complain that I dont have an explicit cast >> specified in my type? I know you cannot have both implicit and explicit >> defined but if im stating I need to envoke an explicit cast - it somehow >> "understands" i really mean execute the implicit cast method.. If the >> answer to this q is "well, thats the way it is...", i guess I can live >> with that. :-) > > Well, "thats the way it is" is pretty close to it, but its not complete, > ;). Basically the rules are an explicit cconversion must be explicitly > declared(using a cast operator), while an implicit cast may or may not be > explicit. In my opinion this is done to allow for exactly what you are > seeing here, that is permit the coder to explicitly tell the compiler to > perform a conversion in a situation where implicit conversions are not in > effect. > >> 2) Do conversions of types only happen during overloading? What are the >> other circumstances? > > Implicit conversions are possible during any assignment, return or > parameter pass operation(both of which you could consider an assignment > and look like or are assignments in other languages). Overload resolution > takes conversions in account to determine the proper overload, assignment > takes it in account to determine if any conversion steps are required > between the source and the target type, casting can obviously explicitly > cause a conversion, a return statement can cause . > > I don't think there are any other circumstances where this happens, but I > don't have the spec on hand to be sure(can't recall off hand if implicit > conversions to bool are considered in if statements, for example). > >> 3) I noticed that this pattern causes an infinite loop. Shouldnt the >> complier choke at this? >> >> static public implicit operator StringWrapper(String val) { >> val += " (im changed)"; >> //return new StringWrapper(val); >> return val; >> } >> > > The compiler should probably spit out a warning that you are going to > enter an infinite loop, but it *is* legal code. The reason for this is > that the compiler cannot really tell that the infinite recursion is going > to happen, just that its likely or possible. While its obvious to us, > without being able to understand the method as a whole, the compiler could > only guess as to if you actually meant to cause recursion or not. Thus it > is something it should probably warn about, but not emit an error. > I guess the first step is understanding what implicit and explicit
operators are. What they effectively do, is convert one type to another. The difference between implicit and explicit operators, is whether or not you need to cast or not. Consider your own code, and assume for now you didn't implement the implicit operator: StringWrapper sw = new StringWrapper("some value"); string s = sw; // this will fail if you don't have an implicit operator string s = (string)sw; // this fail if you don't have an explicit operator. One thing I've noticed developers have to understand, is that converting from one type to another, doesn't just happen magically, code needs to exist, which in this case, is the implicit and explicit operators. It looks like what you're trying to do, is build additional functionality into the string class. You probably tried what many of us already did, and do: public class StringWrapper : System.String {} You probably also realized, that this is impossible, because System.String is a sealed class (along with most of the other primitive types you'd like to extend from time to time), so this prevents you from inheriting from it. Your best bet, would be to keep your implicit operators in place, to ease development. But in your example: static public void printMe(StringWrapper val) { //Console.Write(val.ToLower()); //old Console.Write(((string)val).ToLower()); } The parameter "val" is of type StringWrapper, and not string. You can easily convert between the two using your implicit operators, but that doesn't mean their methods are inherited from each other. In order to use the ToLower() method, you will need to get a variable of type string, because it's the string class which has that method defined, not your StringWrapper. Since you have your implicit operator defined, this a pretty simple process: static public void printMe(StringWrapper val) { //Console.Write(val.ToLower()); //old string newVal = val; Console.Write(newVal.ToLower()); } I hope this clarifies what your understanding of implicit conversions, and how they're used. Brant Estes Thanks for your reply Brant. It helped. Indeed, your right. I did try and
start this out by extending the String class - but I noticed that the String class was sealed in the docs... then I started to think of a way to do what I need to do with *minimum* impact to the calling code and the executing code. Then i remembered that String objects can be created without having to do a "new". And then it struck me there has to be a way I can create an string and assign it to my own type without a "new". Passing objects into method parameters seemed like writing stringwrapper a = "xyz" to me and thats where all this started from. At that time I didnt know this concept is called operator overloading. But now I know. :-) Girish "Brant Estes" <bra***@magenic.com> wrote in message I guess the first step is understanding what implicit and explicitnews:1111729696.059576.139420@g14g2000cwa.googlegroups.com... operators are. What they effectively do, is convert one type to another. The difference between implicit and explicit operators, is whether or not you need to cast or not. Consider your own code, and assume for now you didn't implement the implicit operator: StringWrapper sw = new StringWrapper("some value"); string s = sw; // this will fail if you don't have an implicit operator string s = (string)sw; // this fail if you don't have an explicit operator. One thing I've noticed developers have to understand, is that converting from one type to another, doesn't just happen magically, code needs to exist, which in this case, is the implicit and explicit operators. It looks like what you're trying to do, is build additional functionality into the string class. You probably tried what many of us already did, and do: public class StringWrapper : System.String {} You probably also realized, that this is impossible, because System.String is a sealed class (along with most of the other primitive types you'd like to extend from time to time), so this prevents you from inheriting from it. Your best bet, would be to keep your implicit operators in place, to ease development. But in your example: static public void printMe(StringWrapper val) { //Console.Write(val.ToLower()); //old Console.Write(((string)val).ToLower()); } The parameter "val" is of type StringWrapper, and not string. You can easily convert between the two using your implicit operators, but that doesn't mean their methods are inherited from each other. In order to use the ToLower() method, you will need to get a variable of type string, because it's the string class which has that method defined, not your StringWrapper. Since you have your implicit operator defined, this a pretty simple process: static public void printMe(StringWrapper val) { //Console.Write(val.ToLower()); //old string newVal = val; Console.Write(newVal.ToLower()); } I hope this clarifies what your understanding of implicit conversions, and how they're used. Brant Estes |
|||||||||||||||||||||||