web-dev-qa-db-ja.com

割り当ての左側でヌル条件演算子を使用する

いくつかのページがあり、それぞれにDataという名前のプロパティがあります。別のページで、このデータを次のように設定しています。

if (MyPage1 != null)
    MyPage1.Data = this.data;
if (MyPage2 != null)
    MyPage2.Data = this.data;
if (MyPage3 != null)
    MyPage3.Data = this.data;

MyPageでnull条件演算子を使用する可能性はありますか?私はこのようなものを考えています:

MyPage?.Data = this.data;

しかし、このように書くと、次のエラーが発生します。

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

MyPageがnullになり、左側が変数にならないためです。

すでに持っているように使用できないわけではありませんが、これにnull条件演算子を使用する可能性があるかどうかを知りたいだけです。

29
diiN__________

Null伝播演算子は値を返します。また、割り当ての左側に値ではなく変数を指定する必要があるため、この方法では使用できません。

確かに、tenary演算子を使用して物事を短くすることはできますが、その一方で、読みやすさの面では実際には役立ちません。

ヨアヒム・イサクソンのあなたの質問へのコメントは、うまくいくはずの異なるアプローチを示しています。

10
Allmighty

Joachim Isakssonがコメントで示唆したように、私は今メソッドSetData(Data data)を持ち、次のように使用します:

MyPage1?.SetData(this.data);
MyPage2?.SetData(this.data);
MyPage3?.SetData(this.data);
7
diiN__________

私は次の拡張子を思いつきました、

public static class ObjectExtensions
{
    public static void SetValue<TValue>(this object @object, string propertyName, TValue value)
    {
        var property = @object.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
        if (property?.CanWrite == true)
            property.SetValue(@object, value, null);
    }
}

グローバルに呼び出すことができます。これはパブリックプロパティでのみ機能します。

myObject?.SetValue("MyProperty", new SomeObject());

以下の改良版は何でも動作しますが、

public static void SetValue<TObject>(this TObject @object, Action<TObject> assignment)
{
    assignment(@object);
}

世界的に呼ばれることもある

myObject?.SetValue(i => i.MyProperty = new SomeObject());

ただし、Actionは割り当てのみを必要としないため、拡張名は誤解を招く可能性があります。

2
James M

パーティーにはかなり遅れましたが、同様の問題でこの記事に行きました。以下のように、SetValueメソッドのアイデアを取り入れ、汎用の拡張メソッドを作成しました。

/// <summary>
/// Similar to save navigation operator, but for assignment. Useful for += and -= event handlers. 
/// If <paramref name="obj"/> is null, then <paramref name="action"/> is not performed and false is returned.
/// If <paramref name="obj"/> is not null, then <paramref name="action"/> is performed and true is returned.
/// </summary>
public static bool SafeAssign<T>(this T obj , Action<T> action ) where T : class 
{
  if (obj is null) return false;
  action.Invoke(obj);
  return true;
}

イベントハンドラーのアタッチとデタッチの使用例:

public void Attach() => _control.SafeAssign(c => c.MouseDown += Drag);

public void Detach() => _control.SafeAssign(c => c.MouseDown-= Drag);

誰かがそれが便利だと思うことを願っています:)

1
Paul Williams

これを試してくださいすべてのページをmyPageListに追加してください。

IEnumerable<MyPage> myPageList;

foreach(MyPage myPage in myPageList)
{
if (myPage != null)
    myPage.Data = this.data;
}

一般的なSetValue拡張メソッド(ただし、refプロパティのみ)は次のようになります。

    public static void SetValue<T>(this T property, T value)
    {
        property = value;
    }

のように使用されます

ButtonOrNull?.Visibility.SetValue(Visibility.Hidden);
0
copa017