?[]とは何ですか?C#の構文?


85

実際に抽象クラスであるデリゲートを研究しているときに、Delegate.cs理解できない次のメソッドを見ました

  • 戻り値が?すでにreference(class)型であるにもかかわらず使用する理由
  • ?[]? パラメータの意味

説明してもらえますか?

public static Delegate? Combine(params Delegate?[]? delegates)
{
    if (delegates == null || delegates.Length == 0)
        return null;

    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}


23
null可能な値を含むことができるnull可能な配列ではありませんか?
Cid

3
c#8では、オブジェクト変数をnullにすることを許可しないように指定できるようになりました。あなたがそのコンパイラフラグを反転した場合は、すべての変数を指定する必要がありますされて nullにすることができます。
ジェレミー

回答:


66

ステップバイステップの説明:

params Delegate?[] delegates -それはnull可能の配列です Delegate

params Delegate?[]? delegates -配列全体をnullにすることができます

各パラメータはタイプであるため Delegate?あり、Delegate?[]?配列のインデックスを返すので、戻り値の型がDelegate?そうでない場合、コンパイラーintは、文字列を返すメソッドから、再実行している場合と同様にエラーを返します。

たとえば、次のDelegateような型を返すようにコードを変更できます。

public static Delegate Combine(params Delegate?[]? delegates)
{
    Delegate defaulDelegate = // someDelegate here
    if (delegates == null || delegates.Length == 0)
        return defaulDelegate;

    Delegate d = delegates[0] ?? defaulDelegate;
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}

4
私の最初の質問はどうですか?戻り値が?すでに参照(クラス)型であるにもかかわらず使用する理由
snr-Reonica Monica

2
デリゲートであるdを返すからですか?タイプ。また、パラメータに応じてnullまたはデリゲート
Athanasios Kataras

2
@snr戻り値は?、引数値がを使用するのとまったく同じ理由でを使用し?ます。後者を理解すれば、前者も自動的に理解できます。メソッドがnullを返す可能性があるため、パラメータがnullを受け入れる場合があります。つまり、両方にnullが含まれる可能性があります
GSerg

2
触った。私はその例を使って第2部として答えました。Since each parameter is of the type Delegate? and you return an index of the Delegate?[]? array, then it makes sense that the return type is Delegate?
Athanasios Kataras

2
@snr:戻り値が使用する理由 それはすでにreference(class)型ですが(1)構造体が同様のコードで使用されている場合、それは習慣またはリファクタリングの残りかもしれません(2)C#8では、参照型は本質的にnull可能であることが許可されません(したがって明示的なnull可能性が必要です( 3)Foo?きちんとしたHasValue特性を持っているが、チェックFooする必要がある== null(4)メソッドシグネチャを読み取る開発者に、nullが可能であることが予想され、正しい結果であることを通知する(5)コードは、
ヌル可能性

25

null可能参照型はC#8.0で新しく追加されました。以前は存在しませんでした。

それはドキュメントの問題であり、コンパイル時の警告がどのように生成されるかです。

「オブジェクトがオブジェクトのインスタンスに設定されていない」という例外は、ごく一般的なものです。しかし、これはランタイム例外であり、コンパイル時にすでに部分的に検出されている可能性があります。

規制については、Delegate dいつでも電話できます

 d.Invoke();

つまり、コードを記述できます。コンパイル時には何も起こりません。実行時に例外が発生する場合があります。

新しい間 Delegate? pこのコードのために

 p.Invoke();

コンパイラ警告を生成します。 CS8602: Dereference of a possibly null reference あなたが書いていない限り:

 p?.Invoke();

つまり、nullでない場合にのみ呼び出します。

したがって、変数にnullが含まれる場合と含まれない場合があります。以前に警告を発し、nullの複数のテストを回避できます。intとintの場合と同じです。確かに、1つはnullではなく、1つをもう1つに変換する方法を知っています。


確かでDelegateはありませんが、それがnullでないことを確認してください。あなたはあなたが確かに知っているふりをします(ほとんどの場合それで十分です)。
Tim Pohlmann

@TimPohlmann int i = nullと同様に、文字列s = nullも不可能です(この重大な変更を含むC#8では)。だから、それは何かのふりをするだけです。下位互換性のため、警告にダウングレードされています。警告をエラーにアップグレードすると、nullではないことが確実にわかります。
Holger

4
前回チェックしたところ、NRTは100%防弾ではありません。コンパイラが検出できない特定のエッジケースがあります。
Tim Pohlmann

はい。ただし、これは「変数が初期化されていません」または「すべてのコードパスが値を返すわけではない」という警告と同じです。これらはすべて、実行時に検出されることなく、100%コンパイル時の機能です。int?とは異なり、余分な情報を保持するために余分なメモリを追加しないと思います。それで、それがインテリセンスと同じくらい信頼できるとしましょう。かなり良い。
Holger

1
あなたが持っている場合、intそれはnullになることはありません。あなたが持っている場合、Delegateそれはnullになる可能性があります(反射などのさまざまな理由で)。通常、Delegate(NRTが有効になっているC#8では)nullでないと仮定しても安全ですが、確実にはわかりません(どこintで確実にわかっているか)。
Tim Pohlmann

5

C#8では、参照型をnull可能として明示的にマークする必要があります。

デフォルトでは、これらの型にはnullを含めることができません。これは、値の型に似ています。これによって内部の動作が変わることはありませんが、型チェッカーでは手動で行う必要があります。

与えられたコードはC#8で動作するようにリファクタリングされていますが、この新機能のメリットはありません。

public static Delegate? Combine(params Delegate?[]? delegates)
{
    // ...[]? delegates - is not null-safe, so check for null and emptiness
    if (delegates == null || delegates.Length == 0)
        return null;

    // Delegate? d - is not null-safe too
    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}

この機能を利用した更新されたコード(機能せず、単なるアイデア)の例を次に示します。ヌルチェックから私たちを救い、この方法を少し簡略化しました。

public static Delegate? Combine(params Delegate[] delegates)
{
    // `...[] delegates` - is null-safe, so just check if array is empty
    if (delegates.Length == 0) return null;

    // `d` - is null-safe too, since we know for sure `delegates` is both not null and not empty
    Delegate d = delegates[0];

    for (int i = 1; i < delegates.Length; i++)
        // then here is a problem if `Combine` returns nullable
        // probably, we can add some null-checks here OR mark `d` as nullable
        d = Combine(d, delegates[i]);

    return d;
}

2
those types are not able to contain null、エラーではなくコンパイラ警告を生成することに注意してください。コードは正常に実行されます(ただし、NullReferenceExceptionsが生成される可能性があります)。これは、下位互換性を考慮して行われます。
JAD
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.