我定义了以下结构:

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 给出以下编译时错误:

运算符必须在参考类型或无效类型中使用

那是什么意思?我该如何解决它?

有帮助吗?

解决方案

结构体是一种值类型,因此它不能与 as 操作员。这 as 如果转换失败,运算符必须能够分配 null 值。这仅适用于引用类型或可为空值类型。

有几种方法可以解决这个问题,但最好的办法是改变你的 Call 从结构类型到类。这实际上会将您的类型从值类型更改为引用类型,从而允许 as 如果转换失败,运算符分配 null 值。

有关值类型与值类型的更多信息参考类型, 是一篇不错的文章。另外,看看MSDN:

其他提示

一些现有的答案不是 相当 正确的。你不能使用 不可为空 类型与 as, ,因为结果 as 如果第一个操作数实际上不是适当的类型,则为该类型的 null 值。

然而,你 使用 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 为 null - 您可以将 null 值转换为引用类型(或可为 null 值类型)的变量,但不能转换为不可为 null 值类型。

从C#规格

  

§7.10.11as运算符被用来   明确将值转换为一个给定的   的引用类型或的空类型即可。与强制转换表达式   (§7.7.6),as运算符从不抛出   一个例外。相反,如果   指示的转换是不可能的,   所得到的值是<强>空

参考和空类型可以为空。 Stucts是值类型,所以他们不能为空。

Call? call = line.Tag as Call?;

它的C#的限制。如果类型是引用类型,那么如果转换失败,它只会返回“空”,但因为它是值类型,不知道什么时候转换失败什么返回。

您必须更换您的使用视为有两个:“是”和“为”

if (line.Tag is Call) {
  call = (Call)line.Tag;
} else {
  // Do whatever you would do if as returned null.
}

的含义是什么 - 。如所述的,结构是值类型

我怎样才能解决这个问题 - 将其更改为

Call call = line.Tag;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top