返回Task <t>的默认值或null

时间:2018-07-10 22:39:27

标签: c# async-await

我有一个关于Cache库的包装器,并且具有以下方法来检索基于Key的缓存值:

public async Task<T> GetAsync<T>(string key)
{
    var serializedObject = await _cache.GetStringAsync(key);

    return JsonConvert.DeserializeObject<T>(serializedObject);
}

问题是缓存中没有任何内容,我从DeserializeObject方法收到错误。我被困在什么都没有存储缓存时如何返回null或T的默认值的问题上。

我尝试过:

public async Task<T> GetAsync<T>(string key)
{
    var serializedObject = await _cache.GetStringAsync(key);

    if (serializedObject == null) return Task.CompletedTask;

    return JsonConvert.DeserializeObject<T>(serializedObject);
}

但是Task.CompletedTask无法转换为Task<T>

我尝试过:

public async Task<T> GetAsync<T>(string key)
    {
        var serializedObject = await _cache.GetStringAsync(key);

        if (serializedObject == null) return Task.FromResult<T>(null);

        return JsonConvert.DeserializeObject<T>(serializedObject);
    }

但是null不是T的有效参数。

如何获取GetAsync以返回null或T的默认值?

更新

我有以下工作要做:

public async Task<T> GetAsync<T>(string key)
{
    var serializedObject = await _cache.GetStringAsync(key);

    return serializedObject == null ? default(T) : JsonConvert.DeserializeObject<T>(serializedObject);
}

2 个答案:

答案 0 :(得分:3)

您有三个选择:

  • 如果不需要支持值类型,请添加T : class约束
  • 添加一个包装器类,使您的调用者知道访问缓存是否成功,或者
  • 添加一种在检索失败时构造和缓存新值的方法。

第一个实现使您的方法可以编译:

public async Task<T> GetAsync<T>(string key) where T : class {
    var serializedObject = await _cache.GetStringAsync(key);
    if (serializedObject == null) {
        return await Task.FromResult<T>(null);
    }
    return JsonConvert.DeserializeObject<T>(serializedObject);
}

这是第二个实现:

class CacheResult<T> {
    public bool IsSuccess {get;}
    public T Value {get;}
    public CacheResult(T val, bool isSuccess) {
        Value = val;
        IsSuccess = isSuccess;
    }
}
public async Task<CacheResult<T>> GetAsync<T>(string key) {
    var serializedObject = await _cache.GetStringAsync(key);
    if (serializedObject == null) {
        return new CacheResult(default(T), false);
    }
    return new CacheResult(
        JsonConvert.DeserializeObject<T>(serializedObject)
    ,   true
    );
}

这是第三个实现:

public async Task<T> GetAsync<T>(string key, Func<string,T> make) {
    var serializedObject = await _cache.GetStringAsync(key);
    if (serializedObject == null) {
        var res = make(key);
        _cache.PutStringAsync(key, JsonConvert.SerializeObject(res));
        return res;
    }
    return JsonConvert.DeserializeObject<T>(serializedObject);
}

如果无法使用缓存的对象,则调用者需要为第二种方法提供“工厂”委托,以便创建新对象。

答案 1 :(得分:0)

您尝试过吗? return default(T);

由于要返回默认值T,因此最好同步返回。