为什么我不能在结构中使用as关键字?

时间:2021-07-04 06:52:29

I defined the following struct:

我定义了以下结构:

public struct Call
{
    public SourceFile caller;
    public SourceFile callee;

    public Call(SourceFile caller, SourceFile callee)
    {
        this.caller = caller;
        this.callee = callee;
    }
}

Later, I assign it to the Tag property of another object:

稍后,我将其分配给另一个对象的Tag属性:

line.Tag = new Call(sf1, sf2);

But when I try to retrieve the Tag property like so,

但是当我尝试像这样检索Tag属性时,

Call call = line.Tag as Call;

Visual Studio gives the following compile-time error:

Visual Studio提供以下编译时错误:

The operator as must be used within a reference type or nullable type

必须在引用类型或可空类型中使用运算符

What is the meaning of that? And how can I solve it?

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

6 个解决方案

#1


31  

A struct is a value type, so it cannot be used with the as operator. The as operator must be able to assign a value of null if the cast fails. This is only possible with a reference type or a nullable value type.

struct是值类型,因此不能与as运算符一起使用。如果转换失败,as运算符必须能够赋值null。这仅适用于引用类型或可空值类型。

There are a couple ways to solve this, but your best bet is to change your Call type from a struct to a class. This will essentially change your type from a value type to a reference type, which allows the as operator to assign a value of null if the cast fails.

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

For more information on value types vs. reference types, this is a decent article. Also, have a look on MSDN:

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

#2


32  

Some of the existing answers aren't quite right. You can't use non-nullable types with as, because the result of as is the null value of the type if the first operand isn't actually of an appropriate type.

一些现有的答案并不完全正确。您不能将非可空类型与as一起使用,因为如果第一个操作数实际上不是合适的类型,则as的结果是该类型的空值。

However, you can use as with value types... if they're nullable:

但是,您可以使用值类型...如果它们可以为空:

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

So you could use:

所以你可以使用:

Call? call = line.Tag as Call?;

Then you can use it as:

然后你可以用它作为:

if (call != null)
{
    // Do stuff with call.Value
}

Two caveats though:

但有两点需要注意:

  • In my experience this is slower than just using is followed by a cast
  • 根据我的经验,这比使用后跟一个演员要慢
  • You should seriously reconsider your current Call type:
    • It's exposing public fields, which is generally poor encapsulation
    • 它暴露了公共领域,这通常是很糟糕的封装
    • It's a mutable value type, which is almost certainly a mistake
    • 这是一个可变的值类型,几乎肯定是一个错误
  • 你应该认真重新考虑你当前的Call类型:它暴露了公共字段,这通常是不好的封装它是一个可变的值类型,这几乎肯定是一个错误

I would strongly suggest you make it a class instead - at which point this problem goes away anyway.

我强烈建议你把它变成一个班级 - 无论如何这个问题都会消失。

Another thought: if the tag should always be a Call, then it's better to cast it:

另一个想法:如果标签应该始终是一个Call,那么最好将其转换为:

Call call = (Call) line.Tag;

That way, if the data doesn't match your expectation (i.e. there's some bug such that the Tag isn't a Call) then you get to find out about it early, rather than after you've potentially done some other work. Note that this cast will behave differently depending on whether Call is a struct or a class, if Tag is null - you can cast a null value to a variable of a reference type (or a nullable value type), but not to a non-nullable value type.

这样,如果数据与您的期望不符(即,有一些错误,使得标签不是一个呼叫),那么您可以尽早找到它,而不是在您可能完成其他工作之后。请注意,根据Call是一个结构还是一个类,如果Tag为null,这个转换将表现不同 - 您可以将null值转换为引用类型的变量(或可空值类型),但不能转换为非可空值类型。

#3


12  

From the C# Spec

来自C#规范

§7.10.11 The as operator is used to explicitly convert a value to a given reference type or nullable type. Unlike a cast expression (§7.7.6), the as operator never throws an exception. Instead, if the indicated conversion is not possible, the resulting value is null.

§7.10.11as运算符用于将值显式转换为给定的引用类型或可空类型。与强制转换表达式(第7.7.6节)不同,as运算符从不抛出异常。相反,如果无法指示转换,则结果值为空。

References and nullable types can be null. Stucts are value types so they can't be null.

引用和可空类型可以为null。 Stucts是值类型,因此它们不能为null。

#4


1  

Call? call = line.Tag as Call?;

#5


0  

It's a limitation of C#. If the type were a reference type, then if the cast failed it would simply return 'null', but since it's a value type, it doesn't know what to return when the cast fails.

这是C#的限制。如果类型是引用类型,那么如果转换失败,它将只返回'null',但由于它是一个值类型,它不知道在转换失败时返回什么。

You must replace your use of as with two: 'is' and 'as'

您必须将以下两种用法替换为:'is'和'as'

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

#6


-1  

What is the meaning - As stated, structures are value types.

意义是什么 - 如上所述,结构是价值类型。

How can I solve it - Change it to

我怎样才能解决它 - 改成它

Call call = line.Tag;

#1


31  

A struct is a value type, so it cannot be used with the as operator. The as operator must be able to assign a value of null if the cast fails. This is only possible with a reference type or a nullable value type.

struct是值类型,因此不能与as运算符一起使用。如果转换失败,as运算符必须能够赋值null。这仅适用于引用类型或可空值类型。

There are a couple ways to solve this, but your best bet is to change your Call type from a struct to a class. This will essentially change your type from a value type to a reference type, which allows the as operator to assign a value of null if the cast fails.

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

For more information on value types vs. reference types, this is a decent article. Also, have a look on MSDN:

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

#2


32  

Some of the existing answers aren't quite right. You can't use non-nullable types with as, because the result of as is the null value of the type if the first operand isn't actually of an appropriate type.

一些现有的答案并不完全正确。您不能将非可空类型与as一起使用,因为如果第一个操作数实际上不是合适的类型,则as的结果是该类型的空值。

However, you can use as with value types... if they're nullable:

但是,您可以使用值类型...如果它们可以为空:

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

So you could use:

所以你可以使用:

Call? call = line.Tag as Call?;

Then you can use it as:

然后你可以用它作为:

if (call != null)
{
    // Do stuff with call.Value
}

Two caveats though:

但有两点需要注意:

  • In my experience this is slower than just using is followed by a cast
  • 根据我的经验,这比使用后跟一个演员要慢
  • You should seriously reconsider your current Call type:
    • It's exposing public fields, which is generally poor encapsulation
    • 它暴露了公共领域,这通常是很糟糕的封装
    • It's a mutable value type, which is almost certainly a mistake
    • 这是一个可变的值类型,几乎肯定是一个错误
  • 你应该认真重新考虑你当前的Call类型:它暴露了公共字段,这通常是不好的封装它是一个可变的值类型,这几乎肯定是一个错误

I would strongly suggest you make it a class instead - at which point this problem goes away anyway.

我强烈建议你把它变成一个班级 - 无论如何这个问题都会消失。

Another thought: if the tag should always be a Call, then it's better to cast it:

另一个想法:如果标签应该始终是一个Call,那么最好将其转换为:

Call call = (Call) line.Tag;

That way, if the data doesn't match your expectation (i.e. there's some bug such that the Tag isn't a Call) then you get to find out about it early, rather than after you've potentially done some other work. Note that this cast will behave differently depending on whether Call is a struct or a class, if Tag is null - you can cast a null value to a variable of a reference type (or a nullable value type), but not to a non-nullable value type.

这样,如果数据与您的期望不符(即,有一些错误,使得标签不是一个呼叫),那么您可以尽早找到它,而不是在您可能完成其他工作之后。请注意,根据Call是一个结构还是一个类,如果Tag为null,这个转换将表现不同 - 您可以将null值转换为引用类型的变量(或可空值类型),但不能转换为非可空值类型。

#3


12  

From the C# Spec

来自C#规范

§7.10.11 The as operator is used to explicitly convert a value to a given reference type or nullable type. Unlike a cast expression (§7.7.6), the as operator never throws an exception. Instead, if the indicated conversion is not possible, the resulting value is null.

§7.10.11as运算符用于将值显式转换为给定的引用类型或可空类型。与强制转换表达式(第7.7.6节)不同,as运算符从不抛出异常。相反,如果无法指示转换,则结果值为空。

References and nullable types can be null. Stucts are value types so they can't be null.

引用和可空类型可以为null。 Stucts是值类型,因此它们不能为null。

#4


1  

Call? call = line.Tag as Call?;

#5


0  

It's a limitation of C#. If the type were a reference type, then if the cast failed it would simply return 'null', but since it's a value type, it doesn't know what to return when the cast fails.

这是C#的限制。如果类型是引用类型,那么如果转换失败,它将只返回'null',但由于它是一个值类型,它不知道在转换失败时返回什么。

You must replace your use of as with two: 'is' and 'as'

您必须将以下两种用法替换为:'is'和'as'

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

#6


-1  

What is the meaning - As stated, structures are value types.

意义是什么 - 如上所述,结构是价值类型。

How can I solve it - Change it to

我怎样才能解决它 - 改成它

Call call = line.Tag;