pattern-matching
でnullable int
を使用するのが好きです。つまり、int?
:
int t = 42;
object tobj = t;
if (tobj is int? i)
{
System.Console.WriteLine($"It is a nullable int of value {i}");
}
ただし、これにより、次の構文エラーが発生します。
「i)」は赤い波線でマークされています。
古い演算子is
を使用すると、式がコンパイルされます。
int t = 42;
object tobj = t;
if (tobj is int?)
{
System.Console.WriteLine($"It is a nullable int");
}
string t = "fourty two";
object tobj = t;
if (tobj is string s)
{
System.Console.WriteLine($@"It is a string of value ""{s}"".");
}
また、期待どおりに動作します。
(私は c#-7.2 を使用しており、 。net-4.7.1 と 。net-4.6の両方でテストしています.1 )
演算子の優先順位と関係があると思いました。したがって、私はいくつかの場所で括弧を使用しようとしましたが、これは役に立ちませんでした。
なぜこれらの構文エラーが発生するのですか?どうすればそれらを回避できますか?
コードを次のように変更します。
int t = 42;
object tobj = t;
if (tobj is Nullable<int> i)
{
Console.WriteLine($"It is a nullable int of value {i}");
}
これにより、より役立つものが生成されます。
その他(ユーザー @ Blue0500 at github )は、この動作をバグ Roslynの問題#20156 としてタグ付けしています。 Roslyn issue#20156 に反応して、Microsoftの Julien Couvreur は、それは仕様によるものだと考えていると述べています。
Roslynに取り組んでいるMicrosoftのNeal Gafter も、 null許容型の使用にはより良い診断が必要であると述べています 。
したがって、エラーメッセージは次を使用して回避できます。
int t = 42;
object tobj = t;
if (tobj == null)
{
Console.WriteLine($"It is null");
}
else if (tobj is int i)
{
Console.WriteLine($"It is a int of value {i}");
}
解析時の 問題tobj is int? i
を除いて、なぜtobj is int? i
またはtobj is Nullable<int> i
が許可されないのかという疑問が残ります。
Nullableでパターンマッチングを実際に使用する方法を知りたい人は、次のような一般的なヘルパー関数を使用して行うことができます。
_public static bool TryConvert<T>(object input, out T output)
{
if (input is T result)
{
output = result;
return true;
}
output = default(T);
// Check if input is null and T is a nullable type.
return input == null && System.Nullable.GetUnderlyingType(typeof(T)) != null;
}
_
true
がT
に含まれるのと同じタイプのnull許容または非null可能である場合、またはinput
がnullでinput
がnull可能である場合、これはT
を返します。基本的には通常と同じように機能しますが、null許容型も処理します。
補足:興味深いことに、私のテストから、Tがnull許容の場合、System.Nullable.GetUnderlyingType(typeof(T))
が呼び出されるたびに40バイトのガベージが割り当てられることがわかりました。理由はわかりませんが、私にはバグのように思えますが、通常のように単にnullチェックするのではなく、多額の費用がかかる可能性があります。
それを知って、ここにもっと良い関数があります:
_public static bool TryConvert<T>(object input, out T? output) where T : struct
{
if (input is T result)
{
output = result;
return true;
}
output = default(T?);
return input == null;
}
_