C#: 'is'キーワードとNotのチェック


287

これはばかげた質問ですが、このコードを使用して、何かが特定のタイプかどうかを確認できます...

if (child is IContainer) { //....

「NOT」インスタンスをチェックするよりエレガントな方法はありますか?

if (!(child is IContainer)) { //A little ugly... silly, yes I know...

//these don't work :)
if (child !is IContainer) {
if (child isnt IContainer) { 
if (child aint IContainer) { 
if (child isnotafreaking IContainer) { 

はい、はい...ばかげた質問....

コードがどのように見えるかについていくつかの質問があるので、それはメソッドの最初の単なる戻りです。

public void Update(DocumentPart part) {
    part.Update();
    if (!(DocumentPart is IContainer)) { return; }
    foreach(DocumentPart child in ((IContainer)part).Children) {
       //...etc...

105
個人的には「こどもがノタケない...」が好き。私はそのキーワードをC#5に入れるように投票しています
ジョセフ

これを使用する状況を知りたいですか?このコードの「else」の部分はどのように見え、単にテストを反転させることはできませんか?コードが「子がIContainerでない場合は例外をスローする」または「子がIContainerでない場合は多分それはIFooなので、次に試してみる」と言っている場合、そこに暗黙のelseステートメントはありませんか?私はおそらく何かを逃している。
マーティンペック

1
@ MartinPeck、else句がない可能性があります。それが私がこれを検索した理由です。
Joshua Walsh

@MartinPeckはここにサンプルがあります:-ifをif (!(argument is MapsControlViewModel vm)) { return; }反転して、メソッドの残りの部分をifの角かっこ内に置くことができますが、クリスマスツリーのコードが表示され、メソッドの終わりに多くの右角かっこがあります。それははるかに読みにくいです。
ANeves 2018

おそらく、一般的に必要なのはifnotステートメントです
Dave Cousineau

回答:


301
if(!(child is IContainer))

行く唯一の演算子です(演算子はありませんIsNot)。

それを行う拡張メソッドを作成できます。

public static bool IsA<T>(this object obj) {
    return obj is T;
}

そしてそれを使用して:

if (!child.IsA<IContainer>())

そして、あなたはあなたのテーマに従うことができます:

public static bool IsNotAFreaking<T>(this object obj) {
    return !(obj is T);
}

if (child.IsNotAFreaking<IContainer>()) { // ...

更新(OPのコードスニペットを考慮):

後で実際に値をキャストするので、as代わりに次のように使用できます。

public void Update(DocumentPart part) {
    part.Update();
    IContainer containerPart = part as IContainer;
    if(containerPart == null) return;
    foreach(DocumentPart child in containerPart.Children) { // omit the cast.
       //...etc...

1
ck:オペレーターという意味では、何もありませIsNotん。
Mehrdad Afshari、

5
はい。はっきりしない場合は冗談です。
Mehrdad Afshari

111

あなたはこの方法でそれを行うことができます:

object a = new StreamWriter("c:\\temp\\test.txt");

if (a is TextReader == false)
{
   Console.WriteLine("failed");
}

2
@フランク-はい、isキーワードはブール値を与えます。これはfalseと比較できます
cjk

32
@Frankはに比べてis優先順位が高いため機能し==ます。使用できない唯一の理由!x is fは、に比べて優先順位が低いためです!
Mehrdad Afshari、

私はこれが好きですが、変数を導入するとき、それが必要であるにもかかわらず、正しく機能していないようです。if (a is TextReader reader == false)動作するはずですが、初期化されていない可能性があると言って、真のパスで変数を使用することはできません。
Dave Cousineau

@DaveCousineau-通常、導入された変数を使用する場合は、変数をタイプチェックして導入します。out
タイプチェックが

@StingyJack 真のパスで、変数が初期化されていないと見なされる、ある種のグリッチがありますif (a is TextReader reader == true)変数が初期化されていないと考えても、
Dave Cousineau

11

elseを使用しないのはなぜですか?

if (child is IContainer)
{
  //
}
else
{
  // Do what you want here
}

そのすっきりした使い慣れたシンプルな?


3
何も問題はありません-これはちょっとした質問です。何かが特定のタイプではない場合、関数をすぐに終了したいと思いました。私はそれを永遠にやりました(!(child is Something))が、もっと良い方法がないことを確認したいと思いました。
Hugoware、2009年

1
問題のサンプルコードでは、これは空のifブラケットを意味します。それは賢明な代替案のように聞こえません。
ANeves 2018

9

あなたが持っている方法は問題ありません、一連の拡張メソッドを作成して、「 'NOT'インスタンスを確認するよりエレガントな方法」を作成できます。

public static bool Is<T>(this object myObject)
{
    return (myObject is T);
}

public static bool IsNot<T>(this object myObject)
{
    return !(myObject is T);
}

それからあなたは書くことができます:

if (child.IsNot<IContainer>())
{
    // child is not an IContainer
}

7

これはまだ言及されていません。それは動作し、私はそれを使用するよりも良く見えます!(child is IContainer)

if (part is IContainer is false)
{
    return;
}

is構文: expr is constant、ここでexprは評価する式で、constantはテストする値です。


3
同様にあなたがすることができますif (part as IContainer is null)。正直なところどちらが良いかわかりません。
Flynn1179

5

醜い?同意しません。他の唯一の方法(私は個人的にこれは「醜い」だと思います):

var obj = child as IContainer;
if(obj == null)
{
   //child "aint" IContainer
}

@Mehrdad-Nullable?これを使用できるようにするのではなく、機能させることができます。これは醜い方法のほんの一例です。
stevehipwell、2009年

@ Steveo3000:はい、しかし明示的に言及すべきですか?あるas句は。obj as int常にコンパイル時エラーです。
Mehrdad Afshari、

@Mehrdad-同意しました、BFreeはこれを反映するために彼の投稿を編集することができました。'obj as int?'を提供します。
stevehipwell、2009年

@ Stevo3000:しかし、何も問題はないと思います。IContainerは、値の型ではなくインターフェイスのように感じます。指摘したいのは、値の型に注意する必要があり、必ずしもisフォームの直接変換ではないということです。
Mehrdad Afshari、

オプションでif(obj == default(IContainer))を実行できます。これにより、値の型と参照の型が処理されます
Joseph

3

isあなたはそれ以外の場合はブール値で行うことができるようになる何かを行うことができますので、オペレータは、boolean型の結果を評価します。否定するには、!演算子を使用します。なぜこれだけのために別のオペレーターが必要なのですか?


5
別の演算子ではありません。かっこの余分なセットを削除できるキーワードがあるかどうか疑問に思っていました。それは主要な一瞬ですが、私は興味がありました。
Hugoware、2009年

オッケー、わかりました。あなたの例から、私はあなたが新しい専用のオペレーターを探しているという印象を受けました。
Brian Rasmussen、

私はこのような特別な演算子を持つことは悪いことだと思います。なぜなら、この方法(とにかくこのansについて説明します)があるからです。別の操作がある場合、同じことを達成するには2つの方法があり、混乱する可能性があります。
BuddhiP 2014年

3

拡張メソッドIsNot<T>は、構文を拡張する良い方法です。心に留めて

var container = child as IContainer;
if(container != null)
{
  // do something w/ contianer
}

のようなことをするよりもパフォーマンスが良い

if(child is IContainer)
{
  var container = child as IContainer;
  // do something w/ container
}

あなたの場合、メソッドから戻るので問題ではありません。つまり、型のチェックとその直後の型変換の両方を行わないように注意してください。


3

これは括弧の問題を回避しませんが、Google経由でアクセスする人々のために、コードの残りの部分を少しきれいにするために新しい構文が(C#7以降)存在することを言及する必要があります:

if (!(DocumentPart is IContainer container)) { return; }
foreach(DocumentPart child in container.Children) {
    ...

これにより、二重キャスト、nullチェック、およびnullの可能性があるスコープで変数を使用できるようになります。


2

通常、IS演算子が最善の方法ですが、状況によっては使用できる代替手段があります。as演算子を使用して、nullかどうかをテストできます。

MyClass mc = foo as MyClass;
if ( mc == null ) { }
else {}

2

C#9は、論理的なパターンが含まれます(.NET 5でリリースされる)andorそしてnot私たちは、よりエレガントにこれを書くことを可能にします、:

if (child is not IContainer) { ... }

同様に、このパターンを使用してnullを確認できます。

if (child is not null) { ... }

この変更を追跡するGithubの問題の詳細を確認できます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.