What's wrong with the ?? operator used like this: - c#

So insteed of writing:
if (obj.Collection == null)
obj.Collection = new Collection();
obj.Collection.Add(something);
I thought of writing:
obj.Collection = obj.Collection ?? new Collection;
obj.Collection.Add(something);
It kind of feels wrong, especially this part "obj.Collection = obj.Collection..."
What do you guys think ?
Regards,

If I had to choose between these two blocks of code, I would use the former. It's more readable and it's a common pattern. ?? is useful in scenarios where you need to default a value (e.g., DateTime date = nullableDateTimeInstance ?? defaultDate;).
But frankly, I'd try to not end up in situation where I want to add to collection and it's possible that the collection is null. Instead, I'd make sure that the collection is initialized in the constructor or whatever the case may be.

Do you mean:
if (obj.Collection == null)
{
obj.Collection = new Collection();
}
obj.Collection.Add(something);
If so, you can rewrite it as
(obj.Collection = (obj.Collection ?? new Collection())).Add(something);

The code will emit an unnecessary assignment (of obj.Collection to itself) if obj.Collection is not null, but other than that it is equivalent to the original.
Looks fine to me provided you don't use it in time critical sections. Anyway it's possible the compiler can optimise the assignment away, but I don't know if it would or not.
Perhaps it just feels wrong because the original code is such a common and simple pattern that it feels wrong to change it.

I'd say it also depends on what the setter of the Collection property does. Consider this:
public Collection Collection
{
get { return _collection; }
set
{
_collection = value;
Thread.Sleep( 1000 ); // or some expensive real work
}
}
In this case, the assignment obj.Collection = obj.Collection ?? new Collection() would be really costly.
However, if you need to create a collection "on demand", it's common to use a similar pattern in the property getter, like this:
public Collection Collection
{
get { return _collection ?? ( _collection = new Collection() ); }
}

Related

Assignment of property if not null, possible with null-coalecing?

I'm trying to do smth like
Im trying to assign property on an object if this object is not null.
but standard form of non-null invocation does not work for assignment like this
socket?.Blocking = false
what I'm trying to do is shorten this if possible:
if(socket != null) socket.Blocking = false
This would be a great feature
b?.c = "bob"
Though, it's flawed when it comes to compound assignments. Consider this
a.b?.c = "bob"
What should it do on null?
Personally, I think it should just ignore the parents. But alas, the powers that be have probably made the right decision to disallow this because of inconsistency with the other use cases of null conditional.
Note : you could roll your own an extension method, though it's not very satisfying, and would probably fail my code reviews just on abstractness and readability.
a?b.NullConditional(x => x.c = "bob");
You are left with
if(a?.b != null) a.b.c = "bob"
or in your case
if(socket != null) socket.Blocking = false
or to write a dedicated extension method for this use case.
I think the only way would be to use an extension method, so you could write:
socket?.SetBlocking(false);
You can create the extension method like this:
public static class SocketExtensions
{
public static void SetBlocking(this Socket socket, bool blocking)
{
if (socket != null) socket.Blocking = blocking;
}
}

C# null-conditional shorthand for method arguments

The null-conditional operator is very useful when the method belongs to the object in question, but what if the object in question is an argument? For example, can this be shortened?
var someList = new List<SomeType>();
if (anotherList.Find(somePredicate) != null)
{
someList.Add(anotherList.Find(somePredicate))
}
One solution I thought of was to use an extension method like below:
public static void AddTo<T>(this T item, List<T> list)
{
list.Add(item);
}
With that the first code block can be reduced to:
var someList = new List<SomeType>();
anotherList.Find(somePredicate)?.AddTo(someList);
But this solution is specific to this example (i.e. adding an object to a list if it's not null). Is there a general way to indicate that if a parameter is null, the method should not be run?
Never do this
var someList = new List<SomeType>();
if (anotherList.Find(somePredicate) != null)
{
someList.Add(anotherList.Find(somePredicate))
}
this will search the list twice which is unnecessary. use a temporary variable instead.
var someList = new List<SomeType>();
var find = anotherList.Find(somePredicate);
if (find != null) someList.Add(find);
Is there a general way to indicate that if a parameter is null, the method should not be run?
Currently there is no such feature. how ever there are other alternatives that work better like in other answers provided.
You could also use just:
var someList = new List<SomeType>();
someList.AddRange(anotherList.Where(somePredicate));
In your case you probably need to make sure that your predicate only finds at max one element.
TLDR: Not yet.
The team plans to implement a functionality into the language, that would do this exact thing. It would look something like this:
someList.Add(anotherList.Find(somePredicate) ?? return);
In which the ?? return checks whether the first argument is null, and if it is, than it returns. (Or you could write break if that is what you want)
I am not sure if this is a thing they are working on at the moment, and if it will be included in the next version of C#, but would go a long way if it is going to be.

Creating an object via lambda factory vs direct "new Type()" syntax

For example, consider a utility class SerializableList:
public class SerializableList : List<ISerializable>
{
public T Add<T>(T item) where T : ISerializable
{
base.Add(item);
return item;
}
public T Add<T>(Func<T> factory) where T : ISerializable
{
var item = factory();
base.Add(item);
return item;
}
}
Usually I'd use it like this:
var serializableList = new SerializableList();
var item1 = serializableList.Add(new Class1());
var item2 = serializableList.Add(new Class2());
I could also have used it via factoring, like this:
var serializableList = new SerializableList();
var item1 = serializableList.Add(() => new Class1());
var item2 = serializableList.Add(() => new Class2());
The second approach appears to be a preferred usage pattern, as I've been lately noticing on SO. Is it really so (and why, if yes) or is it just a matter of taste?
Given your example, the factory method is silly. Unless the callee requires the ability to control the point of instantiation, instantiate multiple instances, or lazy evaluation, it's just useless overhead.
The compiler will not be able to optimize out delegate creation.
To reference the examples of using the factory syntax that you gave in comments on the question. Both examples are trying (albeit poorly) to provide guaranteed cleanup of the instances.
If you consider a using statement:
using (var x = new Something()) { }
The naive implementation would be:
var x = new Something();
try
{
}
finally
{
if ((x != null) && (x is IDisposable))
((IDisposable)x).Dispose();
}
The problem with this code is that it is possible for an exception to occur after the assignment of x, but before the try block is entered. If this happens, x will not be properly disposed, because the finally block will not execute. To deal with this, the code for a using statement will actually be something more like:
Something x = null;
try
{
x = new Something();
}
finally
{
if ((x != null) && (x is IDisposable))
((IDisposable)x).Dispose();
}
Both of the examples that you reference using factory parameters are attempting to deal with this same issue. Passing a factory allows for the instance to be instantiated within the guarded block. Passing the instance directly allows for the possibility of something to go wrong along the way and not have Dispose() called.
In those cases, passing the factory parameter makes sense.
Caching
In the example you have provided it does not make sense as others have pointed out. Instead I will give you another example,
public class MyClass{
public MyClass(string file){
// load a huge file
// do lots of computing...
// then store results...
}
}
private ConcurrentDictionary<string,MyClass> Cache = new ....
public MyClass GetCachedItem(string key){
return Cache.GetOrAdd(key, k => new MyClass(key));
}
In above example, let's say we are loading a big file and we are calculating something and we are interested in end result of that calculation. To speedup my access, when I try to load files through Cache, Cache will return me cached entry if it has it, only when cache does not find the item, it will call the Factory method, and create new instance of MyClass.
So you are reading files many times, but you are only creating instance of class that holds data just once. This pattern is only useful for caching purpose.
But if you are not caching, and every iteration requires to call new operator, then it makes no sense to use factory pattern at all.
Alternate Error Object or Error Logging
For some reason, if creation fails, List can create an error object, for example,
T defaultObject = ....
public T Add<T>(Func<T> factory) where T : ISerializable
{
T item;
try{
item = factory();
}catch(ex){
Log(ex);
item = defaultObject;
}
base.Add(item);
return item;
}
In this example, you can monitor factory if it generates an exception while creating new object, and when that happens, you Log the error, and return something else and keep some default value in list. I don't know what will be practical use of this, but Error Logging sounds better candidate here.
No, there's no general preference of passing the factory instead of the value. However, in very particular situations, you will prefer to pass the factory method instead of the value.
Think about it:
What's the difference between passing the parameter as a value, or
passing it as a factory method (e.g. using Func<T>)?
Answer is simple: order of execution.
In the first case, you need to pass the value, so you must obtain it before calling the target method.
In the second case, you can postpone the value creation/calculation/obtaining till it's needed by the target method.
Why would you want to postpone the value creation/calculation/obtaining? obvious things come to mind:
Processor-intensive or memory-intensive creation of the value, that you want to happen only in case the value is really needed (on-demand). This is Lazy loading then.
If the value creation depends on parameters that are accessible by the target method but not from outside of it. So, you would pass Func<T, T> instead of Func<T>.
The question compares methods with different purposes. The second one should be named CreateAndAdd<T>(Func<T> factory).
So depending what functionality is required, should be used one or another method.

whats the best pattern for removing this duplication

I have the following code I am trying to consolidate. (here are two examples) but with this repeated pattern of checking if fields are null then if they are different and if yes, then setting the new value into the old value.
What is the best way to rewrite this to avoid duplication?
if (String.IsNullOrEmpty(f.FirstName))
{
if (exisingPerson.FirstName != f.FirstName)
{
change = true;
exisingPerson.FirstName = f.FirstName;
}
}
if (String.IsNullOrEmpty(f.LastName))
{
if (exisingPerson.LastName != f.LastName)
{
change = true;
exisingPerson.LastName = f.LastName;
}
}
I don't think you can do much to remove the duplication (at least not without introducing reflection which will probably just muddy the code rather than make it clearer).
However you could look at implementing INotifyPropertyChanged which is a standard pattern for notifying about changes to an object instead of the boolean you are currently using:
How to: Implement the INotifyPropertyChanged Interface
If you look at the example code there it also has a certain amount of repetition.
You can use delegates:
public static bool ChangeProperty(Func<Person, string> getter, Action<Person, string> setter, Person person, string value)
{
if (!String.IsNullOrEmpty(value) && !getter(person).Equals(value))
{
setter(person, value);
return true;
}
return false;
}
and call it with lambdas like this:
var barneyRubble = new Person();
change = ChangeProperty(p => p.FirstName, (p, v) => p.FirstName = v, barneyRubble, "Fred");
An even better thing to do would be to put the method in the Person class and eliminate that third parameter altogether, replacing it with this.
Probably overkill, but if you're making a lot of these kind of property changes it might be valuable, and I think it's an interesting pattern anyway.
For just a couple of fields, your code may be the best. Short and simple.
If you're doing this a lot, you could use reflection to iterate through each field in the object, and perform the operation if it's a String.
However, the downside of this is readability. Perhaps you're better off being explicit, and protecting against typos through copy/paste through extensive use of unit tests.

Good practices for initialising properties?

I have a class property that is a list of strings, List.
Sometimes this property is null or if it has been set but the list is empty then count is 0.
However elsewhere in my code I need to check whether this property is set, so currently my code check whether it's null and count is 0 which seems messy.
if(objectA.folders is null)
{
if(objectA.folders.count == 0)
{
// do something
}
}
Any recommendation on how this should be handled?
Maybe I should always initialise the property so that it's never null?
When I have List as a property, I usually have something that looks like the following (this is not a thread safe piece of code):
public class SomeObject
{
private List<string> _myList = null;
public List<string> MyList
{
get
{
if(_myList == null)
_myList = new List<string>();
return _myList;
}
}
}
Your code would then never have to check for null because the Property would be initialized if used. You would then only have to check for the Count.
Right now your code will Always throw a Null Pointer exception, you are checking for Null and if it IS null - you're trying to access an object which does not exist.
If for your application the collection being a null reference never has a different meaning than the collection being empty, then yes, I would say you should always initialize it and this way remove the null checks from the remaining code.
This approach only makes sense if the property setter does not allow to change it to a null reference after initialization.
You have three options (and you need to decide based on your project):
Create a method to check for NullOrNoElements. Pro: Allows both null and no entries. Con: You have to call it everywhere you want to use the property.
Preinitialize with a list. Pro: Thread-save and very easy. Con: will use memory even when not used (depending on how many instances you have this may be a problem)
Lazy initialize Pro: Does only use memory when really used. Con: NOT thread save.
private List<string> lp = null;
public List<string> ListProp
{
get
{
if(lp == null)
lp = new List<string>();
return lp;
}
}
You could always initialize the property so it's an empty List. Then you can just check the count property.
List<String> Folder = Enumerable.Empty<String>();
I once wrote an extension method for ICollection objects that checked if they were null or empty
public static Boolean IsNullOrEmpty<T>(this ICollection<T> collection)
{
return collection == null ? true : collection.Count() == 0;
}
public static Boolean IsPopulated<T>(this ICollection<T> collection)
{
return collection != null ? collection.Count() > 0 : false;
}
You could do this in a single IF
if(objectA.folders is null || objectA.folders.count == 0)
Or you could create a boolean property in the class which checks this status for you and returns a result
public bool objectA.FolderIsNullOrEmpty
{
get { return objectA.folders is null || objectA.folders.count == 0;}
}
If it does not make a difference to your application, I would rather recomend initializing the List to start with.
You could handle this by initializing the object in the constructor. This is usually where this type of thing is done. Although I see nothing wrong with your current code. No point in initializing stuff that doesn't exist yet, it just wastes memory.
Its a good question. I would add a method to objectA FoldersNullOrEmpty() that you can use eg
public virtual FoldersNullOrEmpty()
{
return (folders == null || folders.count == 0)
}
I almost always initialize lists and even make sure they can't be set to null if exposed by any setters. This makes using them much easier.

Categories

Resources