我定义了以下结构:
public struct Call
{
public SourceFile caller;
public SourceFile callee;
public Call(SourceFile caller, SourceFile callee)
{
this.caller = caller;
this.callee = callee;
}
}
稍后,我将其分配给另一个对象的Tag属性:
line.Tag = new Call(sf1, sf2);
但是当我尝试像这样检索Tag属性时,
Call call = line.Tag as Call;
Visual Studio提供以下编译时错误:
那是什么意思?我该如何解决?必须在a中使用运算符 引用类型或可空类型
答案 0 :(得分:33)
struct是值类型,因此不能与as
运算符一起使用。如果转换失败,as
运算符必须能够赋值null。这仅适用于引用类型或可空值类型。
有几种方法可以解决这个问题,但最好的办法是将Call
类型从结构更改为类。这实质上会将您的类型从值类型更改为引用类型,这允许as
运算符在转换失败时指定null值。
有关值类型与引用类型的更多信息,this是一篇不错的文章。另外,请查看MSDN:
答案 1 :(得分:33)
现有的一些答案并非完全正确。您不能将{em>不可为空的类型与as
一起使用,因为如果第一个操作数实际上不是合适的,as
的结果是该类型的空值类型。
但是, 可以使用as
值类型...如果它们可以为空:
int a = 10;
object o = a;
int? x = o as int?; // x is a Nullable<int> with value 10
long? y = o as long?; // y is a Nullable<long> with the null value
所以你可以使用:
Call? call = line.Tag as Call?;
然后您可以将其用作:
if (call != null)
{
// Do stuff with call.Value
}
但有两点需要注意:
is
后跟投射Call
类型:
我强烈建议你把它变成一个班级 - 无论如何这个问题都会消失。
另一个想法:如果标签总是是Call
,那么最好将其投射:
Call call = (Call) line.Tag;
这样,如果数据与您的期望不符(即有一些错误,Tag
不是Call
),那么您可以尽早找到它,而不是在你潜在完成其他工作之后。请注意,根据Call
是结构还是类,如果Tag
为空,此转换将表现不同 - 您可以将空值转换为引用类型的变量(或可空值类型) ),但不是非可空值类型。
答案 2 :(得分:12)
来自C#Spec
§7.10.11as运算符习惯了 显式地将值转换为给定值 引用类型或可空类型。与演员表达不同 (§7.7.6),as运算符从不抛出 一个例外。相反,如果 指示转换是不可能的, 结果值为 null 。
引用和可空类型可以为null。 Stucts是值类型,因此它们不能为null。
答案 3 :(得分:1)
Call? call = line.Tag as Call?;
答案 4 :(得分:0)
这是C#的限制。如果类型是引用类型,那么如果转换失败,它将只返回'null',但由于它是一个值类型,它不知道在转换失败时返回什么。
您必须将以下两种用法替换为:'is'和'as'
if (line.Tag is Call) {
call = (Call)line.Tag;
} else {
// Do whatever you would do if as returned null.
}
答案 5 :(得分:-1)
含义是什么 - 如上所述,结构是价值类型。
我该如何解决?将其改为
Call call = line.Tag;