当T为集合时,如何返回类型集合。目前它返回null
public static async Task<T> CallWebApi<T>(string url, string accessToken)
{
T result = default(T);
var response = await httpClient.GetAsync(url);
if (response.StatusCode == HttpStatusCode.NotFound)
{
return result; // returns null now. When T is collection, we want to return of
// type collection
}
}
很难为任何可能的T
提供一个好的默认值。对于函数的调用者来说,默认值可能是什么也不清楚。
T
一起使用,而无需猜测任何可能的T
的良好默认值,也不会对调用者造成意外。
public static async Task<T> CallWebApi<T>(string url, string accessToken, T defaultValue)
{
var response = await httpClient.GetAsync(url);
if (response.StatusCode == HttpStatusCode.NotFound)
{
return defaultValue;
}
// else
// get the content and deserialize to T,
// throw an exception if that doesn't work
}
调用者可以这样使用:
var result = await CallWebApi<Model[]>(url, accessToken, Array.Empty<Model>());
可以说,这仍然太复杂了。如果API返回一个空数组怎么办?如何知道空数组是默认值还是实际的API响应?对于可空引用类型,不会以这种方式丢失信息的类型安全模式只需:
public static async Task<T?> CallWebApi<T>(string url, string accessToken) where T: class
{
var response = await httpClient.GetAsync(url);
if (response.StatusCode == HttpStatusCode.NotFound)
{
return null;
}
}
并且调用者不能将T?
作为T
的值而不首先检查它是否为null,这意味着他们不会意外地遇到NullReferenceException
s或其他此类设计问题。
我个人会提供默认值factory parameter:
static async Task<T> CallWebApi<T>(string url, string accessToken, Func<T> defaultFactory = default)
{
var response = await new HttpClient().GetAsync(url);
if (response.StatusCode == HttpStatusCode.NotFound)
{
return defaultFactory is null
? default
: defaultFactory();
}
return default;
}
或者只是默认值本身:
static async Task<T> CallWebApi<T>(string url, string accessToken, T defaultValue = default)
{
...
}
让用户写一些冗长但清晰的代码。
否则,你可以尝试检查类型是否实现了IEnumerable
(见此答案),如果它有无参数的变量(见此答案),并排除一些"角落情况"。如string
(即IEnumerable<char>
),并决定如何处理集合接口(如IList<T>
-这里您需要决定基本集合将使用什么,并通过Type.MakeGenericType()
创建一些反射泛型魔法)。