You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Essentials.Preferences泛型包装类报错及解决方案咨询

Xamarin.Essentials.Preferences 泛型包装类实现方案

你遇到的无法从'T'转换为'string'错误,本质是编译器无法为泛型T匹配到Preferences.Set的对应重载,只能默认尝试调用接收string参数的重载,导致类型转换失败。下面提供两种可行的实现方案:

方案一:利用dynamic自动匹配重载(推荐)

通过dynamic绕过编译时类型检查,让运行时根据实际值的类型匹配Preferences对应的Set/Get重载,代码简洁且兼容所有支持的类型:

public class PreferenceManager
{
    private static PreferenceManager _instance;
    private static readonly object _lock = new object();

    private PreferenceManager() { }

    public static PreferenceManager Instance
    {
        get
        {
            lock (_lock)
            {
                _instance ??= new PreferenceManager();
                return _instance;
            }
        }
    }

    public void SetPreference<T>(string key, T value)
    {
        Preferences.Set(key, (dynamic)value);
    }

    public T GetPreference<T>(string key, T defaultValue = default)
    {
        try
        {
            return (T)(dynamic)Preferences.Get(key, defaultValue);
        }
        catch
        {
            return defaultValue;
        }
    }
}

说明

  • dynamic会在运行时解析实际类型,自动匹配Preferences中对应的重载方法,无需手动枚举类型。
  • 添加默认值参数后,GetPreference的使用体验和原生API一致,读取失败时返回默认值。

方案二:手动枚举支持的类型

如果希望编译时就确定调用的重载,可以手动判断类型并调用对应方法,适合需要严格类型检查的场景:

public class PreferenceManager
{
    private static PreferenceManager _instance;
    private static readonly object _lock = new object();

    private PreferenceManager() { }

    public static PreferenceManager Instance
    {
        get
        {
            lock (_lock)
            {
                _instance ??= new PreferenceManager();
                return _instance;
            }
        }
    }

    public void SetPreference<T>(string key, T value)
    {
        switch (value)
        {
            case string str:
                Preferences.Set(key, str);
                break;
            case int intVal:
                Preferences.Set(key, intVal);
                break;
            case bool boolVal:
                Preferences.Set(key, boolVal);
                break;
            case double doubleVal:
                Preferences.Set(key, doubleVal);
                break;
            case float floatVal:
                Preferences.Set(key, floatVal);
                break;
            case long longVal:
                Preferences.Set(key, longVal);
                break;
            case DateTime dateVal:
                Preferences.Set(key, dateVal);
                break;
            default:
                throw new NotSupportedException($"类型 {typeof(T)} 不被Preferences支持");
        }
    }

    public T GetPreference<T>(string key, T defaultValue = default)
    {
        var type = typeof(T);
        if (type == typeof(string))
            return (T)(object)Preferences.Get(key, defaultValue as string);
        else if (type == typeof(int))
            return (T)(object)Preferences.Get(key, defaultValue is int val ? val : default(int));
        else if (type == typeof(bool))
            return (T)(object)Preferences.Get(key, defaultValue is bool bVal ? bVal : default(bool));
        else if (type == typeof(double))
            return (T)(object)Preferences.Get(key, defaultValue is double dVal ? dVal : default(double));
        // 按需补充其他Xamarin支持的类型
        else
            throw new NotSupportedException($"类型 {type} 不被Preferences支持");
    }
}

注意事项

  • 两种方案都需要确保T是Xamarin.Essentials.Preferences支持的类型(如string、int、bool、DateTime等),否则会抛出异常。
  • 对于可空值类型(如int?),方案一的dynamic方式可自动处理,方案二需要额外添加对应的类型判断分支。

内容的提问来源于stack exchange,提问作者COMAVLER

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 15:20:47