26

新しい C# 6.0 の null 条件演算子は、より簡潔で複雑でないコードを記述するための便利な手段です。customers顧客の配列があると仮定すると、これを使用して nullの場合、長さの代わりに null を取得できます( MSDNの例):

int? length = customers?.Length;

同様に、次のように顧客の代わりに null を取得できます。

Customer first = customers?[0];

より複雑な式でcustomersは、is null、最初の顧客が null、または最初の顧客のOrdersオブジェクトが nullの場合に null が返されます。

int? count = customers?[0]?.Orders?.Count();

しかし、null 条件演算子が対処していないように見える、存在しない顧客の興味深いケースがあります。上記で、nullの顧客、つまりcustomers配列内のエントリが null の場合がカバーされることを見てきました。しかし、それは存在しない顧客とはまったく異なります。たとえば5、3 要素の配列で顧客を探したりn、0 要素のリストで顧客を探したりします。(同じ議論が辞書検索にも当てはまることに注意してください。)

null 条件演算子は、NullReferenceException の影響を無効にすることのみに重点を置いているように思えます。IndexOutOfRangeException または KeyNotFoundException は単独で公開されており、隅に追い詰められており、自力で対処する必要があります。null条件演算子の精神で、それらのケースも処理できるはずです...それが私の質問につながります。

私はそれを逃しましたか?null 条件は、この式を真にカバーするエレガントな方法を提供しますか...

customers?[0]?.Orders?.Count();

...ゼロ番目の要素がない場合は?

4

4 に答える 4

35

いいえ、これはnull条件演算子であり、indexoutofrange条件演算子ではなく、単に次のようなものに対する構文糖衣であるためです。

int? count = customers?[0]?.Orders?.Count();

if (customers != null && customers[0] != null && customers[0].Orders != null)
{
    int count = customers[0].Orders.Count();
}

0 番目の顧客がいない場合は、通常のIndexOutOfRangeException.

これを回避する方法の 1 つは、インデックスをチェックし、存在しない場合は null を返す拡張メソッドを用意することです。

public static Customer? GetCustomer(this List<Customer> customers, int index)
{
    return customers.ElementAtOrDefault(index); // using System.Linq
}

次に、チェックは次のようになります。

int? count = customers?.GetCustomer(0)?.Orders?.Count();
于 2016-05-05T00:44:51.190 に答える
14
customers?.FirstOrDefault()?.Orders?.Count();

ゼロエスなし、問題ありません。

于 2016-05-05T01:38:09.620 に答える
8

NullReference または IndexOutOfRange 例外を発生させずに n 番目の要素を取得する場合は、次を使用できます。

customers?.Skip(n)?.FirstOrDefault()
于 2019-10-15T17:38:59.063 に答える
3

インデックス作成の安全性はサポートされていません。なぜなら、インデクサーは実際には他のタイプのメソッドの構文糖衣に過ぎないからです。

例えば:

public class MyBadArray
{
    public Customer this[int a]
    {
        get
        {
            throw new OutOfMemoryException();
        }
    }
}

var customers = new MyBadArray(); 
int? count = customers?[5]?.Orders?.Count();

これはここで捕まえるべきですか?KeyNotFoundException に似ているが、実装しているコレクションのタイプに固有の例外であるとしたらどうでしょうか。?.追いつくには、機能を継続的に更新する必要があります。

さらに、?.例外をキャッチしません。それらを防ぎます。

var customer = customers?[5];実際には次のようにコンパイルされます。

Customer customer = null;
if (customers != null)
    customer = customers[5];

例外をキャッチすることは、非常に困難になります。例えば:

void Main()
{
    var thing = new MyBadThing(); 
    thing.GetBoss()?.FireSomeone();
}

public class MyBadThing
{
    public class Boss
    {
        public void FireSomeone() 
        { 
            throw new NullReferenceException();
        }
    }
    public Boss GetBoss()
    {
        return new Boss();
    }
}

単純に例外をキャッチする場合は、次のように記述されます。

Boss boss = customer.GetBoss();
try 
{
    boss.FireSomeone();
} catch (NullReferenceException ex) { 

}

FireSomeoneボスが null の場合にスローされる null 参照例外ではなく、実際には 内で例外をキャッチします。

インデックス ルックアップの例外、キーが見つからないという例外などをキャッチする場合も、同様の不適切なキャッチの問題が発生します。

于 2016-05-05T00:55:51.880 に答える