我有一个Field<T>
类,它将Entity
作为索引器参数:
class Entity { ... }
class Field<T>
{
T this[Entity? entity]
{
get
{
...
}
set
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
...
}
}
}
索引器getter应该允许空Entity
值,而setter不应该,如下所示(不幸的是,它没有编译(:
class Field<T>
{
T this[Entity? entity] { get... }
T this[Entity entity] { set... }
}
有可能吗?
我不太确定您在示例代码中要做什么。您将Entity
定义为一个类,这使它成为一个引用类型。您可以向编译器指示它是一个可为null的引用类型,但内部的类型是相同的。这与值类型不同,后者随着?
而变得不同。(请参阅此处。(
所以Entity
和Entity?
是相同的类型,但是int
->CCD_ 9而CCD_;CCD_ 11。
这一点需要注意,因为索引器的定义方式。C#规范说
索引器的formal_parameter_list定义索引器的签名(§7.6(。具体来说,索引器的签名由其形式参数的数量和类型组成。形式参数的元素类型和名称不是索引器签名的一部分。
第14.9节索引器
您的代码
T this[Entity? entity] { get... }
T this[Entity entity] { set... }
由于两个签名相同,因此出现编译错误。
您可以通过各种方式来解决这一问题,并进行不同的权衡。您可以始终允许null和put运行时检查抛出异常。您可以删除setter和getter中的一个或两个,并将它们显式地实现为方法调用(因此您将丢失obj[index]
语法(。您可以将Entity
更改为值类型,并使用不同类型的签名实现两个不同的索引器;下面的例子。
namespace IndexerExample
{
public struct Entity
{
public int Id { get; set; }
}
public class Field<T>
{
private Dictionary<Entity, T> _values = new Dictionary<Entity, T>();
public T this[Entity? e]
{
get
{
if (!e.HasValue)
{
return default(T);
}
return _values[e.Value];
}
}
public T this[Entity e]
{
get
{
return _values[e];
}
set
{
if (_values.ContainsKey(e))
{
_values[e] = value;
}
else
{
_values.Add(e, value);
}
}
}
}
internal class Program
{
static void Main(string[] args)
{
var f = new Field<int>();
var e = new Entity() { Id = 3 };
f[e] = 9;
var x = f[null];
var y = f[e];
}
}
}
这对于索引器来说是不可能的。试试这个:
public T this[Entity? entity]
{
get
{
return this[entity];
}
set
{
// check for not null
this[entity] = value;
}
}
希望能有所帮助!
从这里开始:
[DisallowNull]
public string? ReviewComment
{
get => _comment;
set => _comment = value ?? throw new ArgumentNullException(nameof(value), "Cannot set to null");
}
string? _comment;
在可为null的上下文中,ReviewComment get访问器可以返回null的默认值。编译器警告说,在访问之前必须对其进行检查。此外,它警告调用方,即使它可能为null,调用方也不应该显式地将其设置为null。DisableNull属性还指定了一个前提条件,它不会影响get访问器。当您观察到以下关于的特征时,可以使用DisableNull属性
在核心场景中,变量可能为null,通常是在第一次实例化时。该变量不应显式设置为null。
毫无疑问,您可以使索引器适应这一点。