Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
156 views
in Technique[技术] by (71.8m points)

c# - Why can't I use the as keyword for a struct?

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:

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

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

Call call = line.Tag as Call;

Visual Studio gives the following compile-time error:

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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

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) 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...