'System.Enum' does not contain a definition for 'TryParse'

Frequent Participant

'System.Enum' does not contain a definition for 'TryParse'

I am building the Constant Contact library against .net 3.5.  First it wasn't finding the JSON library so I had to manually add a reference to System.ServiceModel.Web and that fixed that issue.  Thanks to DaveBerard for informing me on how to do that.  Now Extensions.cs is giving me this error:

'System.Enum' does not contain a definition for 'TryParse'


Can you help me with this one?

Thanks

Mike

6 REPLIES 6
Moderator

Hey Mike,

 

TryParse() was added to System.Enum in .Net 4.0 to increase performance when parsing values into an enum.  Prior to 4.0, you need to use the .Parse() method and put it into a try/catch block to catch the exception.  since try/catch blocks of this type of operation are low performance, in 4.0/4.5 it's preferable to use the TryParse() method instead. 

 

Long story short, the change you'd need to make is to unfortunately recode any of the TryParse() method calls for System.Enum into Parse() methods.  While not necessary, it would be best practice to then add a try/catch block around these.  In theory, you would never have a parse failure though since we map all the values we return to the enum and should never return to you an invalid enum value.  It would purely be to make sure that if something did go wrong, you'd be able to catch and handle the exception correctly instead of dumping to a log.

Dave Berard
Senior Product Manager, Constant Contact
Frequent Participant

Thanks Dave.

 

It finds Parse, but another error.  Here is the new error:

The non-generic method 'System.Enum.Parse(System.Type, string, bool)' cannot be used with type arguments

 


And here is the full function:

public static T ToEnum<T>(this string s) where T : struct, IConvertible
        {
            T t;
            return (Enum.Parse<T>(s, true, out t) ? t : default(T));
        }


Thanks

Mike

This is caused by the difference in how TryParse() in 4.0/4.5 works versus how Parse() works in 3.0.  Parse isn't templated so the entire code needs to be rewritten.  Instead of templated method, which is used above, each Parse() line must be manually done based on the the type.  Unfortunately, this means that there is likely a lot of small code changes in many places that would need to be done to make this work in 3.5.  I may be able to take a look at this later today and see if I can have an example of how you could do this for a specific enum, in the meantime here is an example of how Enum.Parse() works: http://msdn.microsoft.com/en-us/library/kxydatf9(v=vs.90).aspx

Dave Berard
Senior Product Manager, Constant Contact

I've just come across this thread after spending several hours trying to figure out why we've been unable to get constant contact up and running with our .NET 3.5 website.

 

 

Within the CTCTWrapper project on GitHub, there is a class RestClient.cs which has a method with the signature:

 

 private CUrlResponse HttpRequest(string url, string method, string accessToken, string apiKey, string data)


Which features a line inside the try/catch which is responsible for posting to your service:

 

response = request.GetResonse() as HttpWebResponse;

 

This hangs and does not time out when running under .NET 3.5.

 

This is caused by the code block a little earlier on in the method:

 

if (data != null)
{
       // Convert the request contents to a byte array and include it
       byte[] requestBodyBytes = System.Text.Encoding.UTF8.GetBytes(data);
       request.GetRequestStream().Write(requestBodyBytes, 0, requestBodyBytes.Length);
}

 


This opens a stream on the request object but does not dispose of it when done. The stream is still open when you call:

 

response = request.GetResonse() as HttpWebResponse;

 

Which results in a hanging process. To resolve this wrap the call within a using block or dispose of it directly:

 

 

if (data != null)
{
       // Convert the request contents to a byte array and include it
       byte[] requestBodyBytes = System.Text.Encoding.UTF8.GetBytes(data);
       using (var stream = request.GetRequestStream())
       {
              stream.Write(requestBodyBytes, 0, requestBodyBytes.Length);
       }
}

 

Adding this allowed us to successfully integrate under .NET 3.5.

 

 

 

 

Thanks for the update there.  We'll make sure to get this fix into pull request soon.

Dave Berard
Senior Product Manager, Constant Contact

Wanted to post an update on this. I've tested and verified that fix and that it still works fine when used under framework 4.0, so that will be pushed to our repository shortly.

 

In addition, here is a 1:1 replacement for the ToEnum method that doesn't require any other code changes:

/// <summary>
        /// Converts a string to its enum representation.
        /// </summary>
        /// <typeparam name="T">Enum type.</typeparam>
        /// <param name="s">String to convert.</param>
        /// <returns>Returns the enum value.</returns>
        public static T ToEnum<T>(this string s) where T : struct, IConvertible
        {
            T t;
            try
            {
                t = (T)Enum.Parse(typeof(T), s, true);
                return t;
                
            } catch
            {
                return default(T);
            }
            
        }

 

Wanted to add that for anyone else who may need to implement this to be compatible with Framework 3.5. I'll also discuss this with the team and see if we can't get this update into the repo properly.

 

Elijah G.
API Support Engineer
Developer Portal

View API documentation, code samples, get your API key.

Visit Page