Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid CultureInfo name not throwing exception #30725

Closed
mikernet opened this issue Aug 30, 2019 · 13 comments
Closed

Invalid CultureInfo name not throwing exception #30725

mikernet opened this issue Aug 30, 2019 · 13 comments

Comments

@mikernet
Copy link
Contributor

As far as I can tell from the CultureInfo constructor and CreateSpecificCulture docs, these two lines should both throw an exception:

new CultureInfo("aaa").Name.Dump();
CultureInfo.CreateSpecificCulture("aaa").Name.Dump();

Upon further inspection it looks like it creates an unknown language culture with a fallback to invariant. This doesn't seem right...the fact that it throws CultureNotFoundException when you give it an invalid name (i.e. "aaaaa") instead of ArgumentException and it doesn't actually throw CultureNotFoundException when the specified culture isn't found is rather odd. The description of the parameter states that it has to be a predefined culture name, which "aaa" is not.

If this is intended behavior then it should probably be documented a little better.

@tarekgh
Copy link
Member

tarekgh commented Aug 30, 2019

This is Windows 10 behavior, every culture name conforms to BCP-47 is a valid culture and Windows will be able to create it. If you have any concern, please report that to Windows through the Feedback hub. .NET is always use whatever the underlying OS is giving.

@tarekgh tarekgh closed this as completed Aug 30, 2019
@mikernet
Copy link
Contributor Author

mikernet commented Aug 30, 2019

What I'm saying is the MSDN documentation that I linked is highly misleading and should be fixed if this is intended behavior, and furthermore the exceptions being thrown are also misleading. An invalid format for the parameter should throw an argument exception, not a culture not found exception. The issue isn't that the culture wasn't found, it's that the argument was malformed. The method executes just fine with cultures it can't find as long as the name is well formed. Neither of those problems have anything to do with Windows 10.

@mikernet
Copy link
Contributor Author

I understand that a breaking change for the exception type is highly unlikely to happen now, but the method's behavior should at least be properly documented because as it stands right now it isn't.

@mikernet
Copy link
Contributor Author

One other issue: the documented behavior of the CreateSpecificCulture method says it throws an exception if "The culture specified by name does not have a specific culture associated with it." Shouldn't a non-existent culture like "aaa" throw an exception here then? How can a non-existent culture have a specific culture associated with it?

These docs lack much needed clarity.

@tarekgh
Copy link
Member

tarekgh commented Aug 30, 2019

Thanks @mikernet for clarifying. feel free to log a doc issue in the repo https://github.com/dotnet/docs.

@mikernet
Copy link
Contributor Author

mikernet commented Aug 30, 2019

I opened an issue in the doc repo (https://github.com/dotnet/docs/issues/14117), but I still feel like the behavior of the methods is incorrect more than the documentation. These behaviors are not defined in Windows, it's up to .NET to decide how it handles the exceptional circumstances and the documented behavior seems much more sane to me than the actual behavior, especially with regards to point number 2 in my doc issue. Why would a call to get a specific culture return a blankly named culture that just falls back to invariant? It seems nonsensical to me.

Are you sure the actual behavior is the intended behavior?

It would seem to me that this line of code should be checking if the culture is one that actually exists and contains a specific culture, and if not then failing with the documented exception behavior.

@tarekgh
Copy link
Member

tarekgh commented Aug 30, 2019

What is happen is when you create a culture with name like "aaa" which is is not one of the names carried by Windows, at that time Windows will try to create it for us and try to fill the culture properties as much it can by matching the language part and country part. for example, if I try to create ja-US which I think not exist, Windows will try to fake the culture by getting the language information from the Japanese language and will get the country information from US and combine it into a new culture. now when passing "aaa" which not matching any language/country, Windows will just use Invariant culture properties for that. And that is what you are seeing.

This is the behavior defined by Windows starting Windows 10 and not really the .NET. the framework just calling the OS for getting the needed information. the code of CreateSpecificCulture is just calling the OS at the end.

@mikernet
Copy link
Contributor Author

mikernet commented Aug 31, 2019

I understand that, but .NET can still choose to wrap the native calls with whatever behavior it deems appropriate. I think it would have been much more intuitive if it behaved the way the docs state that it does (it seems that whoever wrote the docs thinks so too, since apparently they thought that's how it works as well, haha :) and the dev could choose to fallback to invariant in case of an exception or fail or show an error or whatever...but that's neither here nor there at this point, it's much easier to fix the docs than to introduce breaking changes.

A few minutes ago I was surprised to learn that the invariant culture is marked as a specific culture for the "invariant country" region and not a neutral culture, so the behavior of CreateSpecificCulture makes more sense now. I'll revise my doc issue to reflect that.

@mikernet
Copy link
Contributor Author

mikernet commented Aug 31, 2019

I figured out why this is so bloody confusing...the invariant culture is marked as IsNeutralCulture == false but it shows up in the neutral culture list CultureInfo.GetCultures(CultureTypes.NeutralCultures) and doesn't show up in the specific culture list CultureInfo.GetCultures(CultureTypes.SpecificCultures)...how's that for a mind bending flustercuck. Jeez...

Is that supposed to be that way??

@tarekgh
Copy link
Member

tarekgh commented Aug 31, 2019

agree this is confusing but unfortunately this is the behavior since v1.0. But this is also documented here https://docs.microsoft.com/en-us/dotnet/api/system.globalization.cultureinfo.getcultures?view=netframework-4.8

NeutralCultures, which returns all neutral cultures and the invariant culture.

Which implicitly indicating invariant is not neutral culture :-)

@mikernet
Copy link
Contributor Author

mikernet commented Aug 31, 2019

CreateSpecificCulture() docs state that a CultureNotFoundException is thrown if "the culture specified by name does not have a specific culture associated with it."

When would this ever happen? What named culture doesn't have a specific culture associated with it? None of these lines throw an exception:

CultureInfo.GetCultures(CultureTypes.NeutralCultures).Select(c => CultureInfo.CreateSpecificCulture(c.Name)).ToList();
CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => CultureInfo.CreateSpecificCulture(c.Name)).ToList();
CultureInfo.CreateSpecificCulture("");
CultureInfo.CreateSpecificCulture("aaa-XX"); // still works, returns unknown country culture
CultureInfo.CreateSpecificCulture("aaa"); // still works, returns blank name culture

@tarekgh
Copy link
Member

tarekgh commented Aug 31, 2019

This should throw:

CultureInfo.CreateSpecificCulture("This is not a valid culture"); 

As I mentioned the culture name has to comply with the BCP-47 specs. Otherwise we should throw.

@mikernet
Copy link
Contributor Author

mikernet commented Sep 2, 2019

Right, but it says:

name is not a valid culture name.
-or-
The culture specified by name does not have a specific culture associated with it.

So that's already covered by the first part, so I'm trying to figure out what the second part is referring to.

@msftgits msftgits transferred this issue from dotnet/corefx Feb 1, 2020
@msftgits msftgits added this to the 5.0 milestone Feb 1, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants