https://developers.google.com/protocol-buffers/docs/reference/csharp-generated#oneof suggests that TypeOneofCase
will tell you which is set:
Oneof Fields
Each field within a oneof has a separate property, like a regular
singular field. However, the compiler also generates an additional
property to determine which field in the enum has been set, along with
an enum and a method to clear the oneof. For example, for this oneof
field definition
oneof avatar {
string image_url = 1;
bytes image_data = 2;
}
The compiler will generate these public members:
enum AvatarOneofCase
{
None = 0,
ImageUrl = 1,
ImageData = 2
}
public AvatarOneofCase AvatarCase { get; }
public void ClearAvatar();
public string ImageUrl { get; set; }
public ByteString ImageData { get; set; }
If a property is the current oneof "case", fetching that property will
return the value set for that property. Otherwise, fetching the
property will return the default value for the property's type - only
one member of a oneof can be set at a time.
Setting any constituent property of the oneof will change the reported
"case" of the oneof. As with a regular singular field, you cannot set
a oneof field with a string or bytes type to a null value. Setting a
message-type field to null is equivalent to calling the oneof-specific
Clear method.