Here's a cheeky hack that hunts the TryParse method and calls it via a (cached) delegate: using System; using System. Reflection; static class Program { static void Main() { int i; float f; decimal d; if (Test. TryParse("123", out i)) { Console.
WriteLine(i); } if (Test. TryParse("123.45", out f)) { Console. WriteLine(f); } if (Test.
TryParse("123.4567", out d)) { Console. WriteLine(d); } } } public static class Test { public static bool TryParse(string s, out T value) { return Cache. TryParse(s, out value); } internal static class Cache { public static bool TryParse(string s, out T value) { return func(s, out value); } delegate bool TryPattern(string s, out T value); private static readonly TryPattern func; static Cache() { MethodInfo method = typeof(T).
GetMethod( "TryParse", new Type { typeof(string), typeof(T).MakeByRefType() }); if (method == null) { func = delegate(string x, out T y) { y = default(T); return false; }; } else { func = (TryPattern) Delegate. CreateDelegate(typeof(TryPattern),method); } } } }.
Yeah, wow that looks just the ticket! Thanks. Will just have to wait until Monday to try it out at work.
Like it! – Mongus Pong Jan 22 '10 at 22:48 Bummer denied.. The solution looked good, but I am only being passed the data as objects. I don't know the types at compile time.
I realise I haven't formulated my question very well, hence the confusion. This is close though.. very very close, I can still have a go at using the reflection part of it Im sure. – Mongus Pong Jan 25 '10 at 9:45 Woohoo!
Have twisted it about a bit to come up with the solution. See the edit in my post. Many thanks!
– Mongus Pong Jan 25 '10 at 12:42.
If it is not possible to write it without exceptions, you can isolate the problematic code by refactoring it into a method like so: public static bool TryConvert(T t, out U u) { try { TypeConverter converter = TypeDescriptor. GetConverter(typeof(U)); if (!converter. CanConvertFrom(typeof(T))) { you = default(U); return false; } you = (U)converter.
ConvertFrom(t); return true; } catch (Exception e) { if (e. InnerException is FormatException) { you = default(U); return false; } throw; } } Ideally you should be passing in nullable types as the output parameter, so that null represents an undefined value (because it couldn't do a conversion) rather than the default (i.e. 0 for int).
I would argue that this code really should throw exceptions when it can't figure out a conversion. If the two arguments passed in are DateTime. Now and Color.
Fuschsia, you can make no meaningful comparison between them, so any value you return would be wrong. That's the definition of the right time to throw an exception. If you absolutely need to avoid exceptions, it's not possible to do what you want with arbitrary types.
Every type has its own rules about which values it can parse, and the converter has no way to tell that in advance. (That is to say, as you've noticed, it knows that you can sometimes convert a string to a DateTime, but it is not designed to know that "1/1/2010" is a valid DateTime while "Fred" is not. ).
In this circumstance it is perfectly valid for the inputs to be a DateTime and Color. Obviously as their raw datatypes they cannot be compared. That is why I want to check to see if they can be converted so that a useful comparison can be made.
I just want to check, I don't want this to be an error condition. – Mongus Pong Jan 21 '10 at 19:05 So what you want is just a method to check whether a conversion would succeed, without actually doing the conversion? This is not possible with arbitrary types.
TypeConverter is designed to attempt the conversion and throw exceptions on failure. You could check for common types that you know how to handle, like DateTime and Double and such, and call their TryParse methods. But that only works for the types you check.
– Auraseer Jan 21 '10 at 20:00.
So I need a general way to attempt to convert from any type to any type. Easy enough, . Net provides us with the TypeConverter class.
You're asking too much. Class Animal { } class Dog : Animal { } class Cat : Animal { } Should I be able to convert a Cat to a Dog? You'll find your problem is far easier to solve if you specify more precisely (preferably exactly) what you want the behavior of the method to be.So, write down the expected inputs and what you want the output to be in each possible case.
Then your method should write itself. So right now we have this specification: If the main datatype is a DateTime, and I am passed a String, I need to attempt to convert the String to a DateTime to perform a Date comparison. If the String cannot be converted to a DateTime then do a String comparison.
Int CompareTo(DateTime d, object o) { string s = o as string; if(s! = null) { DateTime dt; if(dt. TryParse(s, out dt)) { return d.
CompareTo(dt); } else { return d.ToString(). CompareTo(s); } } throw new InvalidOperationException(); }.
I want a bool TypeConverter. TryConvert( object inObject, out object ConvertedObjected) method. Kinda like DateTime.TryParse.
I want to do exactly what the code sample I posted does, but without the Exception being raised. Im not really doing objects here, just basic variable types : ints, strings, DateTimes.. I thought my question was fairly clear. – Mongus Pong Jan 21 '10 at 17:33 @Pongus: It's not clear.
What are type are you trying to convert inObject to? Are you trying to convert to the type of ConvertedObjected (sic)? – Jason Jan 21 '10 at 17:37 my apologies.It is a grid control.
I need to sort and filter on any data type that is thrown at me as long as it is IComparable. – Mongus Pong Jan 21 '10 at 17:46.
Stores the cache of all types that can be converted to all types. // First get the cached conversion method. ContainsKey ( s.
Type1Cache = _Typess. ContainsKey ( value. Type2Cache = new ConversionCache ( s.
GetType (), value. Add ( value. Type2Cache = type1Cachevalue.
If ( this. // Invoke the cached TryParse method.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.