28

この質問は、説明を徹底するために完全に見直されました。

null が伝播されたオブジェクトに対してプロパティセッターを呼び出すことができないという点で、C# 6.0 の null 伝播演算子の非常に貧弱な制限のように見えることに気付きました(ただし、null が伝播されたオブジェクトに対してプロパティゲッターを呼び出すことはできます) 。 . 生成された IL (これは C# に反映されています)からわかるように、null 伝播を使用してプロパティ セッターを呼び出す機能を制限するものは何もありません。

手始めに、Java スタイルの Get/Set メソッドと public getter/setter アクセスを持つプロパティの両方を持つ単純なクラスを作成しました。

public class Person
{
    public Person(string name, DateTime birthday)
    {
        Name = name;
    }

    public string Name { get; set; }

    public void SetName(string name)
    {
        Name = name;
    }

    public string GetName()
    {
        return Name;
    }
}

次のテスト クラスで null 伝播の機能をテストしました。

public class Program
{
    public static void Main(string[] args)
    {
        Person person = new Person("Joe Bloggs", DateTime.Parse("01/01/1991"));

        // This line doesn't work - see documented error below
        person?.Name = "John Smith";

        person?.SetName("John Smith");

        string name = person?.Name;
    }
}

割り当ての左側は、変数、プロパティ、またはインデクサーでなければなりません。

ただし、このことから、名前を設定する Java の呼び出しによる方法がSetName(...)機能することに気付くかもしれません。また、null 伝播プロパティの値を取得することも機能することに気付くかもしれません。

このコードから生成された C# を見てみましょう。

public static void Main(string[] args)
{
    Person person = new Person("Joe Bloggs", DateTime.Parse("01/01/1991"));
    if (person != null)
    {
        person.SetName("John Smith");
    }
    string arg_33_0 = (person != null) ? person.Name : null;
}

メソッドに対して使用するとSetName、null 伝播は単純なifステートメントに変換され、プロパティ ゲッターに対して使用すると、またはNameの値を取得するために三項演算子が使用されることに注意してください。Namenull

ここで気づいたことの 1 つは、ステートメントを使用する場合と三項演算子を使用する場合の動作の違いですif。セッターを使用する場合、ifステートメントを使用すると機能しますが、三項演算子を使用すると機能しません。

public static void Main(string[] args)
{
    Person person = null;

    if (person != null)
    {
        person.Name = "John Smith";
    }

    person.Name = (person != null) ? "John Smith" : null;
}

この例では、ifステートメントと三項演算子の両方を使用して、 person がそのプロパティnullに割り当てようとする前に存在するかどうかを確認しています。ステートメントは期待どおりNameに機能します。if期待どおり、三項演算子を使用するステートメントは失敗します

オブジェクト参照がオブジェクト インスタンスに設定されていません。

if私の意見では、この制限は、NULL 伝搬をステートメントまたは三項式に変換する C# 6.0 の機能によるものです。ステートメントのみを使用するように設計されていた場合if、プロパティの割り当ては null 伝播を介して機能します。

これまでのところ、これが可能であってはならない理由について説得力のある議論を見たことがありません。したがって、私はまだ答えを探しています!

4

3 に答える 3

28

あなただけではありません!SLaksはこれを問題として提起しました(現在はこちら)

なぜこのようなコードを書くことができないのでしょうか?

Process.GetProcessById(2)?.Exited += delegate { };

そして、「設計上」として一時的に閉鎖された後

?. 演算子は左辺値を生成しないため、これは設計によるものです。

誰かが、プロパティ セッターとイベント ハンドラーに適しているとコメントしました。

たぶん、次のようなプロパティセッターもリクエストに追加します。

Object?.Prop = false;

C#7 の機能要求として再開されました。

于 2015-09-22T11:11:04.090 に答える
6

この方法で null 伝播演算子を使用することはできません。

この演算子を使用すると、式の評価中に null を伝播できます。エラーが示唆しているように、割り当てのターゲットとして正確に使用することはできません。

単純な古い null チェックに固執する必要があります。

if (a != null)
{
    a.Value = someValue;
}
于 2015-09-11T09:03:39.927 に答える