return 类型中引用类型的可空性与覆盖的成员不匹配
Nullability of reference types in return type doesn't match overridden member
我正在使用 API 和 returns JSON,其中一个值可以是 false
或一个对象。为了处理这个问题,我创建了一个自定义 JsonConverter<T>
.
internal class JsonFalseOrObjectConverter<T> : JsonConverter<T> where T : class
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
{
return null;
}
else
{
return JsonSerializer.Deserialize<T>(ref reader);
}
}
}
问题是我收到以下编译器错误:
Possible null reference return.
我可以将返回的类型设置为 T?
但是我会得到错误:
Nullability of reference types in return type doesn't match overridden member.
我该如何解决?
您已声明泛型类型是(不可为空的)T
,但您要返回 null
。这显然是无效的。
如果您不在乎,则需要让转换器实现 JsonConverter<T?>
或使用 null 宽容运算符。
internal class JsonFalseOrObjectConverter<T> : JsonConverter<T?> where T : class
{
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
...
}
public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options)
{
...
}
}
或
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
{
return null!;
}
...
}
最简单的解决方案是 return null!
:
#nullable enable
internal class JsonFalseOrObjectConverter<T> : JsonConverter<T> where T : class
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
{
return null!;
}
else
{
return JsonSerializer.Deserialize<T>(ref reader);
}
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options){}
}
引用 类 可以为空,因此编译器在遇到 T?
时只使用 T
。
更好的选择是创建类似于 F# 的 Option type 的内容,如果设置了值,则包含 Some value,如果值为 false,则包含 None。通过使 Option
成为一个结构,即使 属性 缺失或为空,我们也会得到默认的 None
值:
readonly struct Option<T>
{
public readonly T Value {get;}
public readonly bool IsSome {get;}
public readonly bool IsNone =>!IsSome;
public Option(T value)=>(Value,IsSome)=(value,true);
public void Deconstruct(out T value)=>(value)=(Value);
}
//Convenience methods, similar to F#'s Option module
static class Option
{
public static Option<T> Some<T>(T value)=>new Option<T>(value);
public static Option<T> None<T>()=>default;
}
解串器可以return None()
或者default
如果遇到false:
internal class JsonFalseOrObjectConverter<T> : JsonConverter<Option<T>> where T : class
{
public override Option<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
{
return Option.None<T>(); // or default
}
else
{
return Option.Some(JsonSerializer.Deserialize<T>(ref reader));
}
}
public override void Write(Utf8JsonWriter writer, Option<T> value, JsonSerializerOptions options)
{
switch (value)
{
case Option<T> (_ ,false) :
JsonSerializer.Serialize(writer,false,options);
break;
case Option<T> (var v,true) :
JsonSerializer.Serialize(writer,v,options);
break;
}
}
}
Write
方法展示了如何使用模式匹配处理 Option<T>
。
使用此序列化程序,以下 类 :
class Category
{
public string Name{get;set;}
}
class Product
{
public string Name{get;set;}
public Option<Category> Category {get;set;}
}
可以用 false
为缺失的类别生成序列化:
var serializerOptions = new JsonSerializerOptions
{
Converters = { new JsonFalseOrObjectConverter<Category>() }
};
var product1=new Product{Name="A"};
var json=JsonSerializer.Serialize(product1,serializerOptions);
这 returns :
{"Name":"A","Category":false}
反序列化此字符串 returns 一个 Product
其 Category
是一个没有值的 Option<Category>
:
var product2=JsonSerializer.Deserialize<Product>(json,serializerOptions);
Debug.Assert(product2.Category.IsNone);
模式匹配表达式可用于提取和使用具有值的类别的属性,例如:
string category=product2.Category switch { Option<Category> (_ ,false) =>"No Category",
Option<Category> (var v,true) => v.Name};
或
if(product2.Category is Option<Category>(var cat,true))
{
Console.WriteLine(cat.Name);
}
我正在使用 API 和 returns JSON,其中一个值可以是 false
或一个对象。为了处理这个问题,我创建了一个自定义 JsonConverter<T>
.
internal class JsonFalseOrObjectConverter<T> : JsonConverter<T> where T : class
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
{
return null;
}
else
{
return JsonSerializer.Deserialize<T>(ref reader);
}
}
}
问题是我收到以下编译器错误:
Possible null reference return.
我可以将返回的类型设置为 T?
但是我会得到错误:
Nullability of reference types in return type doesn't match overridden member.
我该如何解决?
您已声明泛型类型是(不可为空的)T
,但您要返回 null
。这显然是无效的。
如果您不在乎,则需要让转换器实现 JsonConverter<T?>
或使用 null 宽容运算符。
internal class JsonFalseOrObjectConverter<T> : JsonConverter<T?> where T : class
{
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
...
}
public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options)
{
...
}
}
或
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
{
return null!;
}
...
}
最简单的解决方案是 return null!
:
#nullable enable
internal class JsonFalseOrObjectConverter<T> : JsonConverter<T> where T : class
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
{
return null!;
}
else
{
return JsonSerializer.Deserialize<T>(ref reader);
}
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options){}
}
引用 类 可以为空,因此编译器在遇到 T?
时只使用 T
。
更好的选择是创建类似于 F# 的 Option type 的内容,如果设置了值,则包含 Some value,如果值为 false,则包含 None。通过使 Option
成为一个结构,即使 属性 缺失或为空,我们也会得到默认的 None
值:
readonly struct Option<T>
{
public readonly T Value {get;}
public readonly bool IsSome {get;}
public readonly bool IsNone =>!IsSome;
public Option(T value)=>(Value,IsSome)=(value,true);
public void Deconstruct(out T value)=>(value)=(Value);
}
//Convenience methods, similar to F#'s Option module
static class Option
{
public static Option<T> Some<T>(T value)=>new Option<T>(value);
public static Option<T> None<T>()=>default;
}
解串器可以return None()
或者default
如果遇到false:
internal class JsonFalseOrObjectConverter<T> : JsonConverter<Option<T>> where T : class
{
public override Option<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.False)
{
return Option.None<T>(); // or default
}
else
{
return Option.Some(JsonSerializer.Deserialize<T>(ref reader));
}
}
public override void Write(Utf8JsonWriter writer, Option<T> value, JsonSerializerOptions options)
{
switch (value)
{
case Option<T> (_ ,false) :
JsonSerializer.Serialize(writer,false,options);
break;
case Option<T> (var v,true) :
JsonSerializer.Serialize(writer,v,options);
break;
}
}
}
Write
方法展示了如何使用模式匹配处理 Option<T>
。
使用此序列化程序,以下 类 :
class Category
{
public string Name{get;set;}
}
class Product
{
public string Name{get;set;}
public Option<Category> Category {get;set;}
}
可以用 false
为缺失的类别生成序列化:
var serializerOptions = new JsonSerializerOptions
{
Converters = { new JsonFalseOrObjectConverter<Category>() }
};
var product1=new Product{Name="A"};
var json=JsonSerializer.Serialize(product1,serializerOptions);
这 returns :
{"Name":"A","Category":false}
反序列化此字符串 returns 一个 Product
其 Category
是一个没有值的 Option<Category>
:
var product2=JsonSerializer.Deserialize<Product>(json,serializerOptions);
Debug.Assert(product2.Category.IsNone);
模式匹配表达式可用于提取和使用具有值的类别的属性,例如:
string category=product2.Category switch { Option<Category> (_ ,false) =>"No Category",
Option<Category> (var v,true) => v.Name};
或
if(product2.Category is Option<Category>(var cat,true))
{
Console.WriteLine(cat.Name);
}