Reputation: 13
Let's imagine the following situation:
public class A
{
private readonly Func<bool> _myFunction;
...
public A(Func<bool> myFunction)
{
_myFunction = myFunction ?? throw new ArgumentNullException();
}
}
public class B
{
private bool _myBool;
public bool MyBool => _myBool;
}
public class C
{
A a;
B b;
...
public void SomeFunction()
{
a = new A( () => (bool)b?.MyBool );
}
}
I would like to have the exception correctly raised in A
constructor since I want _myFunction
to be set to null if b
has not been instantiated.
Basically something like:
if (b == null) {a = new A(null);} else {a = new A(() => b.MyBool);}
I have tried using the null-conditional operator to do so, but I have being unlucky and I just create a reference to a function that returns null
.
Upvotes: 1
Views: 81
Reputation: 8359
The shorter version is probably a = b is null ? new A(null) : new A(() => b.MyBool);
But it's not correct anyway:
Unless b
is readonly, it can be modified and set to null
before a call to the lambda.
b = null;
a.CallMyFunction(); // will call the lambda and fail to evaluate b.MyBool
A workaround is to use a local (and captured) copy of b
to declare the lambda:
var b2 = b;
a = b2 is null ? new A(null) : new A(() => b2.MyBool)
But this time it doesn't respect good practice (SOLID principles):
A
expect a non null function, it's not his responsibility to raise an exception if the caller can't build one.
The code should looks like this:
a = BuildAFromB(b); // pass a copy of b
// ....
// static to avoid ambiguity between the field b and the argument b
// To avoid this, it's in guidelines to prefix fields name with _
// _a, _b, ...
static A BuildAFromB(B b)
{
if (b is null)
throw new ArgumentException();
return new A(() => b.MyBool);
}
Upvotes: -1