Is there a smarter way of protecting foreach loops against NullReference exceptions than this:
if (G_Locatie.OverdrachtFormulierList != null)
{
foreach (OverdrachtFormulier otherform in G_Locatie.OverdrachtFormulierList)
{
...
}
}
I use a lot of foreach loops, often nested, and a lot of variables where e.g. G_Location certainly exists, but datamember .OverdrachtFormulierList may not have been assigned a list use new yet.
Dear friends, thanks for all your comments. After getting the idea of your suggestions, while having a lot of trouble understanding exactly, after digging through the Lasagna code I got to work on, and after some experimentation, I found that the easiest and cleanest way is to simply avoid having the NULL, by proper initialization. While I kind of resist having to initialize the OverdrachtFormulierList in my code, with the risk of forgetting one instance, I found the proper place for initialization, namely in the original class definition.
For simplicity, look at this code:
class MyClass
{
public List<string> items = new List<string>();
public IEnumerator<string> GetEnumerator()
{
return items.GetEnumerator();
}
}
class MyComplexClass
{
private MyClass _itemlist /*= new MyClass()*/;
public MyClass itemlist
{
get { return _itemlist; }
set { _itemlist = value; }
}
}
void Sandbox()
{
MyClass mc /*= new MyClass()*/;
foreach (string Sb in mc.items)
{
string x = Sb;
}
MyComplexClass mcc = new MyComplexClass();
foreach (string Mb in mcc.itemlist) // <--- NullReferenceException
{
string x = Mb;
}
return;
}
The fun thing is that C# seems to protect you from a lot of buggy mistakes. This code will not build if you do not uncomment the initialization in Sandbox(), so the first foreach will not get a NullReferenceException.
However, you'd better uncomment the init in MyComplexClass to avoid the exception in the second foreach. C# will build with and without this initialization.
So it turns out that in my real code I just have to add a simple initialization in the Class definition of G_Locatie.
The only issue now is that I always wanted to simplify the above code with {get; set;} but that would not be possible with the initialization as described. I will have to live with that minor issue.
In fact, on object-type properties, you don't really need the setter.
Finally, I realized that I could not find a proper title for my problem. So far, every problem I had was already answered in this forum, and I feel that I had to post today only because I could not find posts similar to this one. Perhaps someone can come up with title and tags that make this solution better findable.
Yes, your collection properties should return empty collections rather than null. One way you can ensure this is by using a backing field and assigning a new list in the getter:
private List<string> overdrachtFormulierList;
public List<string> OverdrachtFormulierList
{
get
{
return this.overdrachtFormulierList ??
(this.overdrachtFormulierList = new List<string>());
}
set
{
this.overdrachtFormulierList = value;
}
}
You can also use Enumerable.Empty<T> if your types are IEnumerable<T>
One option would be to create an extension method:
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable source)
{
return source ?? Enumerable.Empty<T>();
}
Then:
foreach (var otherform in G_Locatie.OverdrachtFormulierList.EmptyIfNull())
{
...
}
It would still be preferable to always use an empty collection instead of a null reference, mind you.
Related
I have a class that has a field that is being assigned a value from multiple methods.
public class Shape
{
private Point2D m_location;
public void Move()
{
m_location = ...
}
public void Rotate()
{
m_location = ...
}
public void Flip()
{
m_location = ...
}
}
I am getting a warning from NDepend that says:
Don't assign a field from many methods
https://www.ndepend.com/default-rules/Q_Don't_assign_a_field_from_many_methods.html
I am thinking of solving this problem by creating a separate method to assign the value of the field and calling this method from the other methods that currently assign a value to the field.
Here is an example of the code:
private void SetLocation(Point2D point)
{
m_location = location;
}
I want to know if this is a valid way to solve the problem and if it will just hide the code-smell that NDepend detected or actually fix the issue.
Is this a valid way to solve this problem?
No. As you suspect, this is a code smell. What NDepend is complaining about is mutable references; you have code where:
var s = new SomeObject(someInitialization);
var r = s.SomeResult();
// you now have no idea what s contains or if it is even usable any more.
The solution to this is to make SomeObject immutable and return new references instead of changing internals:
public SomeObject Something()
{
return new SomeObject(SomethingDifferentDependingOn(this.something));
}
Now instead of your first example you have:
var s = new SomeObject(someInitialization);
var r = s.Something().Result;
// s is guaranteed to be unchanged.
Yes some times you will need mutable references. In those cases; document them and explain why they have to be mutable. Then you can override NDepend rules on a case-by-case basis to prevent it showing a warning. If you have a code smell, warn people. Do not try to hide it.
The example after your edit is quite different, but the general principle still holds. If you have only a few internal fields that all change in method calls you can still return immutable references, e.g.:
public Shape Move()
{
return new Shape(m_location ...);
}
If you have many internal fields that don't all change, or you need to do something like share private fields you can't easily have immutable reference, but you can still avoid the warning by using accessors:
public Location
{
get { return m_location; }
private set { m_location = value; }
}
Then use Shape.Location exclusively in your internal methods.
I have a hierarchy of classes based on an abstract Device class. The repository of all devices looks a bit like this:
class Hardware
{
public readonly DeviceCollection<Switch> Switches = ...;
public readonly DeviceCollection<Light> Lights = ...;
}
where DeviceCollection implements IEnumerable<T> where T : Device.
I need to enumerate across all devices, and my currently crappy code does this
protected override IEnumerator<Device> enumerate()
{
foreach (var light in Lights)
{
yield return light;
}
foreach (var #switch in Switches)
{
yield return #switch;
}
}
This is not robust as sometimes I add a new bit of hardware, a new DeviceCollection and it's easy to forget to add a new iteration in the above. So I figured a bit of reflection would help - lazily build a list of the DeviceCollection fields and run through that. But what would the declaration of that list look like?
private List<DeviceCollection<T>> _collections;
doesn't compile. Neither does
private List<DeviceCollection> _collections;
How do I declare this list?
Corollary: Tim S's answer - that IEnumerable is covariant - solves my immediate problem. One little glitch left (which I'm sure has a simpler solution!) is how to do the reflection. Here is my ugly ugly ugly hack:
_collections = new List<IEnumerable<Device>>();
var fields = GetType().GetFields( BindingFlags.Instance | BindingFlags.Public );
foreach (var field in fields)
{
if (field.FieldType.Name.Contains( "DeviceCollection" ))
{
_collections.Add( (IEnumerable<Device>)field.GetValue(this) );
}
}
This, because the test
if (field.FieldType == typeof(DeviceCollection<>)
doesn't work.
The declaration would be:
private List<IEnumerable<Device>> _collections;
And you could use it (after setting it up, which you already seem to have a good idea how to do) as easily as:
protected override IEnumerator<Device> enumerate()
{
return _collections.SelectMany(x => x).GetEnumerator();
}
This works because the IEnumerable<T> interface is covariant, meaning that, e.g. an IEnumerable<Switch> (which DeviceCollection<Switch> implements) can be used as an IEnumerable<Device>.
The reason that a DeviceCollection<Switch> can't be used as an DeviceCollection<Device> is that classes and collections can't be covariant - it wouldn't make sense to let you try to Add a Device to an ICollection<Switch>, because it should only contain Switches. But it makes perfect sense to get a Device out of an IEnumerable<Switch>.
I would contend that you just need a single list:
public DeviceCollection<Device> Devices { get; private set; }
and then you can return specific types with Switches for example:
public IEnumerable<Switch> Switches
{
get
{
return this.Devices.OfType<Switch>();
}
}
and so now enumerate just looks like this:
protected override IEnumerator<Device> enumerate()
{
foreach (var d in Devices)
{
yield return d;
}
}
You can declare it:
private List<DeviceCollection<Device>> _collections;
Why do you need a member variable? I'd think you could do
protected override IEnumerable<Device> enumerate()
{
... reflect to get properties of type IEnumerable<Device>
foreach (var prop in properties)
{
foreach (var device in (IEnumerable<Device>)prop.GetValue(this))
{
yield return device;
}
}
}
Per the comments on efficiency, while I disagree with them, and also disagree with the solutions that propose using a single List and OfType, if reflection is too slow/dangerous, you could simplify your original code:
public IEnumerable<Device> GetAll() {
return from list in new IEnumerable<Device>[] {Switches, Lights}
from device in list
select device;
}
I have List with objects of strings and doubles, and I try to call different methods based on the itemtype and their value. In the debugger I can see that the first iteration works fine, but an error shows when entering the second time after a method is called.
If i comment out the methods and put in simple methods it works, so I understand that it something with how I call the methods.
What do I do wrong, and what can I do to make it work?
If there is easier ways to do what I'm trying, please let me know.
public double evaluateExpressionUsingVariableValues(List<Object> anExpression, Dictionary<String, double> variables)
{
foreach (object element in anExpression)
{
if(element.GetType()!=typeof(string))
{
setOperand((double)element);
}
else if (element.GetType() == typeof(string))
{
if (!element.ToString().StartsWith("%"))
performOperation((string)element);
else
setOperand(variables[element.ToString()]);
}
}
return this.operand;
}
If your methods (setOperand, performOperation) modify the collection at all, you will get an exception. You can't modify the collection while you are iterating over it. One method is to create a result collection and add items to it as you change them, rather than trying to modify the collection in-place.
private void Foo() {
foreach(var item in items) {
if (item.IsBad) {
DeleteItem(item); // will throw an exception as it tries to modify items
}
}
}
private void DeleteItem(Item item) {
items.Remove(item);
}
Instead, try:
private void Foo() {
List<Item> result = new List<Item>();
foreach(var item in items) {
if (!item.IsBad) {
result.Add(item); // we are adding to a collection other
// than the one we are iterating through
}
}
items = result; // we are no longer iterating, so we can modify
// this collection
}
Are you sure that none of the methods you are calling is modifying the collection (anExpression) ? This kind of problem is often the result of that. Try replacing the foreach by a for loop and see if you still get the same issue.
So I've got a whole bunch of options, every different page/tab can have their own local options. We'll have maybe 10-15 pages tabs open tops. I need to implement a way to show the global defaults, weather the all the tabs have consistent values. I'm working on the model/viewmodel portion of a WPF app.
I'd love to find a way that is more elegant since I'm having to cut and past roughly the same code 20+ times and just change property names. Maybe this is the problem Dynamics solve, but right now this feels both wrong and painful.
Here is an example of my current solution:
public class Foo
{
private bool fooVar1;
private bool fooVar2;
//lots of these
private decimal fooVar23;
public Foo()
{
}
public bool FooVar1
{
get;
set;
}
//you get the picture...
}
public class FooMonitor
{
private Foo defaultFoo;
private List<Foo> allFoos;
public FooMonitor(Foo DefaultFoo)
{
defaultFoo = DefaultFoo;
}
public void AddFoo(Foo newFoo)
{
allFoos.Add(newFoo);
}
public void AddFoo(Foo oldFoo)
{
allFoos.Remove(oldFoo);
}
public bool IsFooVar1Consistent
{
get
{
Foo[] tempFoos = allFoos.ToArray();
foreach (Foo tempFoo in tempFoos)
{
if (tempFoo.FooVar1 != defaultFoo.FooVar1) return false;
}
return true;
}
}
}
Or am I approaching this problem entirely incorrectly.
As I'm writing this question (After about 2000 lines of code) I'm thinking of how I read that WPF itself implements Dictionary look ups that crawl up to the parent to see if a Property is present and what the value should be.
Well, for a start you are defining both backing fields which will never be used and automatic properties. This is enough for a simple bool property:
public bool FooVar1 { get; set; }
No need for the private field. This greatly reduces the number of lines in your example.
I'd love to find a way that is more
elegant since I'm having to cut and
past roughly the same code 20+ times
and just change property names.
Code generators exist for exactly this purpose. But if you don't want to go that route, you can shorten your code to this:
return allFoos.All(foo => foo.FooVar1 == defaultFoo.FooVar1);
I'm not quite sure what the question is, but if you're looking for some way to unify the IsFoorVarXConsistent code, you could do it using reflection or by passing in an expression:
public bool IsConsistent(Func<Foo, bool> property)
{
foreach (Foo tempFoo in allFoos)
{
if (property(tempFoo) != property(defaultFoo))
return false;
}
return true;
}
Called like this:
bool is1Consistent = IsConsistent(f => f.FooVar1);
As shown this will only work for boolean properties. To extend it to other types, we can make it generic in the property type. However, in this case we cannot use != to test for inequality because not all types define a != operator. Instead we can use the .Equals method and the ! operator:
public bool IsConsistent<T>(Func<Foo, T> property)
where T : struct
{
foreach (Foo tempFoo in allFoos)
{
if (!property(tempFoo).Equals(property(defaultFoo)))
return false;
}
return true;
}
The where T : struct clause restricts this to value types like int, bool and decimal. In particular it will not work on strings. Removing the where constraint allows it to work on strings and other reference types, but creates the possibility of property(tempFoo) being null, which would cause a NullReferenceException when we called .Equals on it. So if you remove the value types constraint then you will need to add error handling for this scenario.
This might be a stupid question, but is there any common practice for initializing collection properties for a user, so they don't have to new up a new concrete collection before using it in a class?
Are any of these preferred over the other?
Option 1:
public class StringHolderNotInitialized
{
// Force user to assign an object to MyStrings before using
public IList<string> MyStrings { get; set; }
}
Option 2:
public class StringHolderInitializedRightAway
{
// Initialize a default concrete object at construction
private IList<string> myStrings = new List<string>();
public IList<string> MyStrings
{
get { return myStrings; }
set { myStrings = value; }
}
}
Option 3:
public class StringHolderLazyInitialized
{
private IList<string> myStrings = null;
public IList<string> MyStrings
{
// If user hasn't set a collection, create one now
// (forces a null check each time, but doesn't create object if it's never used)
get
{
if (myStrings == null)
{
myStrings = new List<string>();
}
return myStrings;
}
set
{
myStrings = value;
}
}
}
Option 4:
Any other good options for this?
In this case, I don't see the reason for the lazy loading, so I would go with option 2. If you are creating a ton of these objects, then the number of allocations and GCs that result would be an issue, but that's not something to consider really unless it proves to be a problem later.
Additionally, for things like this, I would typically not allow the assignment of the IList to the class. I would make this read-only. In not controlling the implementation of the IList, you open yourself up to unexpected implementations.
For Option 1: if you want to force user to initialize something before using your class then best place to force it is in constructor.
For Option 2: If you're not forcing the user then you really have to initialize an empty collection yourself in the constructor/initializer.
For Option 3: Lazy initialization only makes sense if it involves too much work or its a slow/bulky operation.
My vote goes for option 2.
The only real reason for using the lazy loading solution is for an optimization. And the first rule of optimization is "don't optimize unless you've measured" :)
Based on that I would go with the solution least likely to cause an error. In this case that would be solution #2. Setting it in an initializer virtually eliminates the chance of a null ref here. The only way it will occur is if the user explicitly sets it to null.