Bug 21273 - NSUserDefaults API does not take advantage of C# method overloading
Summary: NSUserDefaults API does not take advantage of C# method overloading
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: 7.9.1.x
Hardware: Macintosh Mac OS
: Normal enhancement
Target Milestone: Future Cycle (TBD)
Assignee: Bugzilla
Depends on:
Reported: 2014-07-11 17:50 UTC by Kevin Chen
Modified: 2014-09-08 10:38 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report for Bug 21273 on Developer Community or GitHub if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: Developer Community HTML or GitHub Markdown
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:

Description Kevin Chen 2014-07-11 17:50:27 UTC
In NSUserDefaults, the iOS API has separate methods for each type (stringForKey:, stringArrayForKey:, boolForKey:, etc) because Objective-C does not support overloaded methods. However, C# does, so all of these could be condensed down into a single method which is overloaded with all the correct types. 

As an illustration, here is the kludge I have in my code, which I think should be part of Mono:

        private class SettingsItem<T>
            public string Key;
            private T cachedValue;

            private NSUserDefaults defaults = NSUserDefaults.StandardUserDefaults;

            public SettingsItem(string key)
                this.Key = key;

            public T Get()
                if (cachedValue == null)
                    // I really hope Mono's compiler optimizes this out when it fills out the template
                    if (typeof(T) == typeof(string)) cachedValue = defaults.StringForKey(Key);
                    //else if (typeof(T) == typeof(string[])) cachedValue = defaults.StringArrayForKey(Key);
                    else if (typeof(T) == typeof(int)) cachedValue = defaults.IntForKey(Key);
                    else if (typeof(T) == typeof(bool)) cachedValue = defaults.BoolForKey(Key);
                    else if (typeof(T) == typeof(double)) cachedValue = defaults.DoubleForKey(Key);
                    else if (typeof(T) == typeof(float)) cachedValue = defaults.FloatForKey(Key);
                    else if (typeof(T) == typeof(NSDictionary)) cachedValue = defaults.DictionaryForKey(Key);
                    else if (typeof(T) == typeof(NSData)) cachedValue = defaults.DataForKey(Key);
                    else if (typeof(T) == typeof(NSObject)) cachedValue = defaults[Key];
                return cachedValue;

            public void Set(T newValue)
                cachedValue = newValue;

                if (typeof(T) == typeof(string)) defaults.SetString(newValue, Key);
                // everything else is similar to what's in Get()

                defaults.Synchronize(); // flush the changes to disk -- required
Comment 1 Rolf Bjarne Kvinge [MSFT] 2014-09-08 10:38:57 UTC
It's not possible to create a method overload that depends on the type of the return value, so what you suggest is not possible for the Get method.

For the Set* methods we could create an overloaded Set version, but your code wouldn't be simpler, since the compiler won't automatically convert T to whatever T is when the method is invoked, you'd end up with this code:

if (typeof (T) == typeof(string)) defaults.Set ((string) newValue, Key)
if (typeof (T) == typeof(double)) defaults.Set((double) newValue, Key)

What could be done are generic Set/Get methods (which would be pretty much a copy of your implementation).