1

Pretty simple question, but I couldn't find an answer with some googling.

Suppose I have a class

public class Test {
   bool testBool { get; set; }
}

and a possible null instance

Test? maybeTest = // something that may or may not be null

How can I safely call a setter on that instance? maybeTest.testBool = true throws a NPE if maybeTest is null, and maybeTest?.testBool = true doesn't compile.

Saul Glasman
  • 141
  • 3
  • 2
    Check for null first? `if(maybeTest != null){ maybeTest.testBool = true; }` – mxmissile Jul 12 '21 at 21:32
  • a helper extension method plus `maybeTest?.testBool.SetTo(true)` ? Since `delegateWhichMightBeNull?.Invoke()` works just fine... – Ben Voigt Jul 12 '21 at 21:32
  • 1
    @mxmissile's approach will work, assuming nothing else can change the value of `maybeTest` in the meantime. – mjwills Jul 12 '21 at 21:35
  • (Naturally the extension method should use `ref` on its `this` argument) – Ben Voigt Jul 12 '21 at 21:35
  • 1
    @mjwills: The "what if something else changes it" and "repetition of possibly long expression" problems can both be solved via `is`-introduced variable. `if (maybeA?.maybeB?.maybeC is Test target) target.testBool = true;` – Ben Voigt Jul 12 '21 at 21:37
  • @PeterDuniho My confusion is I can't get it work. https://dotnetfiddle.net/zz2dwe Hence why I asked. I think an `Action` based approach may be simpler. – mjwills Jul 12 '21 at 21:48
  • @mjwills: True, an auto property prevents using `ref`. With `public bool testBool;` instead of `public bool testBool {get; set;}` your fiddle works fine. – Ben Voigt Jul 12 '21 at 21:51
  • @Ben: I think one could infer from the way the relevant paragraph is written, given that it discusses only value types, the restriction. The compiler will tell you soon enough in any case. But you're right, the docs aren't exactly clear on the point. It's informative to read the original proposal: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-7.2/readonly-ref.md#refin-extension-methods – Peter Duniho Jul 12 '21 at 21:57
  • @Ben: _"an auto property prevents using ref"_ -- to be clear, _any_ property prevents using `ref`. It's the property aspect, not the auto-generated aspect. It's true that if one switches to a field, it will work, but on the other hand doing so breaks a number of important encapsulation goals and guidelines. – Peter Duniho Jul 12 '21 at 22:00
  • Besides what has already been said, if you can add a simple method in your Test class, e.g., `public void SetTestValue(bool v) => testBool = v;`, then you can write: `Test test = null; test?.SetTestValue(true);`. Of course it doesn't throw. - Assuming you can modify that class. – Jimi Jul 12 '21 at 22:07
  • 1
    The same if the extension method just calls an action: `public static void SetPropertyValue(this T instance, Action action) where T : class => action?.Invoke(instance); [...] Test test = null; test?.SetPropertyValue(p => p.testBool = true);` – Jimi Jul 12 '21 at 22:28

0 Answers0