I'm new to C#. I have an implicit typed variable defined like this:
var item = doc.DocumentNode.SelectNodes("//body[#id='person']")
.Select(p => p.InnerText);
This var sometimes returns null. And that's where visual studio asks me to handle the ArgumentNullException. But if I do that my var remains unknown to the rest of my try-catch and I can no longer use it.
Someone advised me to use the null object design pattern but I don't how am I supposed to implement it for a var. Does anyone know how I should handle such situations because I'm tired of handling the null case each and every time.
I am assuming, as it seems, that the problem is SelectNodes returning null when no results are found. This is a pattern I come across frequently: a sequence of operations, several of which can return null values, where the production of any null should cause the entire sequence to produce null.
One solution is to use what functional programmers would call the Maybe monad's Bind method:
public static U IfNotNull<T, U>(this T self, Func<T, U> func)
where U : class
{
return (self != null) ? func(self) : null;
}
This will "propagate" nulls rather than throwing exceptions. Then,
doc.DocumentNode
.SelectNodes("//body[#id='person']")
.IfNotNull(nodes => nodes.Select(p => p.InnerText));
If SelectNodes returned IEnumerable<XmlNode>, you could use Enumerable.Empty<>:
(doc.DocumentNode.SelectNodes("//body[#id='person']") ?? Enumerable.Empty<XmlNode>())
.Select(p => p.InnerText);
Or, for better readability, write an extension method to avoid worrying about operator syntax:
public static T Coalesce<T>(this T self, T other)
where T : class
{
return self ?? other;
}
And:
doc.DocumentNode.SelectNodes("//body[#id='person']")
.Coalesce(Enumerable.Empty<XmlNode>())
.Select(p => p.InnerText);
These are all various ways of deferring null checks until you're ready to deal with the results, without having to catch NullPointerExceptions (or ArgumentExceptions in the case of extension methods). Note that any of these that produce null values could produce default values instead if you tossed a simple ?? operator at the end.
IEnymerable<HtmlNode> v = null;
var item = doc.DocumentNode.SelectNodes("//body[#id='person']");
if (item != null)
{
v = item.Select(p => p.InnerText);
}
Related
This code correctly returns one row:
_loadedAssemblies.ForEach(x =>
{
foundTypes.AddRange(from t in x.GetTypes()
where t.GetInterfaces().Contains(typeof(TInterface))
&& t.BaseType.Name.LeftOf('`') == baseClass.Name.LeftOf('`')
select t);
}
However, when I use PredicateBuilder, I get zero rows:
var compiledPredicate = CompiledPredicate<TInterface>();
_loadedAssemblies.ForEach(x =>
{
foundTypes.AddRange(from t in x.GetTypes()
where compiledPredicate.Invoke(typeof(TInterface))
select t);
}
private static Func<Type, bool> CompiledPredicate<T>() where T : class
{
// True means all records will be returned if no other predicates are applied.
var predicate = PredicateBuilder.True<Type>();
// Get types that implement the interface (T).
predicate = predicate.And(t => t.GetInterfaces().Contains(typeof(T)));
// If the config file includes filtering by base class, then filter by it.
if (!string.IsNullOrWhiteSpace(_baseClass))
{
Type baseClass = Type.GetType(_baseClass);
predicate = predicate.And(t => t.BaseType.Name.LeftOf('`') == baseClass.Name.LeftOf('`'));
}
return predicate.Compile();
}
Someone suggested creating a copy of my loop variable, but I tried that and I still get zero rows. I'm not sure why using PredicateBuilder returns no rows. Any idea what I'm missing?
The change that you mentioned in comments (foundTypes.AddRange(x.GetTypes().AsQueryable().Where(compiledPredicate));) had nothing at all to do with the fact that you were using AsQueryable. In the first case you're passing in a hard coded type to each call of your predicate, in the second you're passing the given item from the sequence. Had you removed the AsQueryable and used Enumerable.Where it would also work, or had you passed the current item, rather than a hard coded type, when invoking it that would also work.
So you can simply do:
foundTypes.AddRange(x.GetTypes().Where(compiledPredicate));
Also, when creating the predicate, there's no need to do as much work as you're doing. Expressions take a fair amount of extra work to deal with. With linq to objects you only need to deal with delegates, which are much less finicky.
private static Func<Type, bool> CompiledPredicate<T>() where T : class
{
Func<Type, bool> predicate = t => t.GetInterfaces().Contains(typeof(T));
if (!string.IsNullOrWhiteSpace(_baseClass))
{
Type baseClass = Type.GetType(_baseClass);
return t => predicate(t) &&
t.BaseType.Name.LeftOf('`') == baseClass.Name.LeftOf('`');
}
return predicate;
}
I m using ...
tmpLst = (from e in App.lstAllChilds where e.Id == Id select e).ToList();
where lstAllChilds is the list, which contains some corrupted data as well.
So now i m tying to handle Try-Catch block inside this query.
Please help.
In case if you just want to ignore "bad elements" then:
App.lstAllChilds.SkipExceptions().Where( e => e.Id == Id).ToList();
Extension method:
public static class Extensions
{
public static IEnumerable<T> SkipExceptions<T>(this IEnumerable<T> values)
{
using (var enumerator = values.GetEnumerator())
{
bool next = true;
while (next)
{
try
{
next = enumerator.MoveNext();
}
catch
{
continue;
}
if (next) yield return enumerator.Current;
}
}
}
}
Here is the simplest change you can make to simply exclude items which are null or are raising an exception.
tmpLst = App.lstAllChilds.Where(e =>
{
try
{
return e != null && e.Id == Id;
}
catch
{
return false;
}
}).ToList();
But in my opinion you probably should investigate and solve the underlying problem. This doesn't seem like a scenario where exceptions should be expected.
So, here's the thing. There's language integrated query (Linq), and then there's yielded enumeration (a.k.a. Iterators).
Linq allows you to define an expression tree that is later executed by something that may or may not be C# (for example the expression could be translated into a SQL query). If you're writing linq there is a good chance your query provider (the thing that does the expression translation) does not support exception handling (much less whatever you're doing that throws exceptions).
Interators on the other hand (or "linq to objects") just ends up executing in C#, so you can just go wild with your exception handling.
For example w/ linq to objects you can do this:
var myList = new[] { "1", "2", "BARF", "3" };
var sum = myList.Select(str => {
try {
return Int32.Parse(str);
} catch {
return 0;
}
}).Aggregate((x, y) => x + y);
If you're indeed doing linq to objects, and you just want to skip elements where your source IEnumerable threw an exception check out Vladimir Gondarev's answer.
The important thing to understand however, is that the anonymous function we just passed to that Select call is not an Expression (an uncompiled expression tree), it is a Func (a delegate pointing to compiled c# code), which means that it will run in the .Net process, even if we replaced myList with a linq to entities table (or some other linq provider). The reason for this is that the C# expression syntax does not support blocks, nor does it support try-catch. Unsurprisingly, given that, the SQL-style Linq statements (from xxx select yyy) also do not support try-catch blocks.
However, just because the C# expression syntax doesn't support it doesn't mean you can't do it. But, to be clear, I do not recommend doing this because I highly doubt there is a QueryProvider in existence that supports it (aside from the linq to objects provider). For the curious here's how you would create a lambda expression that contains a try-catch block.
var parseMethod = typeof(Int32).GetMethod("Parse", new[] { typeof(String) });
var param = Expression.Parameter(typeof(String));
var selectExp =
Expression.Lambda<Func<String, Int32>>(
Expression.TryCatch(
Expression.Call(parseMethod, param),
Expression.Catch(typeof(Exception), Expression.Constant(0))
),
param
);
var sum = myList.Select(selectExp).Aggregate((x, y) => x + y);
So when somebody implements a QueryProvider backed by a store that supports exception handling, you could use this.
It depends what exactly you are trying to achieve:
Return the list except "broken" items.
You can try using a Where clause to check and filter them out:
App.lstAllChilds.Where(x => IsValidNode(x, Id)).ToList();
Apparently you need to implement IsValidNode which should check for null, if it can throw an InvalidObjectException (not sure if you can easily detect it but you can always wrap it in a try-catch block) and Id equality. Like that:
private bool IsValidNode(Child c, int id)
{
if (x == null) return false;
try {
return c.Id == id;
}
catch (InvalidObjectException)
{
}
return false;
}
Return an empty list if there are any broken items.
Just wrap the entire thing in a try-catch block
When I am trying to set IsDefault property of each dressing items where match a condition it throws an error saying:
Sequence contains more than one matching sequence.
(this.DressingItems
.Where(xx => xx.DressingInfo.CatID == catId
&& xx.ProductID == this.ProductID)
.Single()).IsDefault = false;
Well, this exception says that at least two items of the sequence DressingItems match your Where condition. The call to Single then causes the exception because it asserts that only one item is passed in.
Reading your question makes me think that you want to do something on each item of the input sequence, so you will probably use a foreach loop:
foreach(var item in this.DressingItems.Where(xx => xx.DressingInfo.CatID == catId && xx.ProductID == this.ProductID))
{
item.IsDefault = false;
}
this.DressingItems.Where(x=> x.DressingInfo.CatID == catId &&
x.ProductID == this.ProductID).ToList()
.ForEach(item=>item.IsDefault = false);
The point of the Single operator is to assert that a given sequence only has one item. For instance when retrieving a specific instance by primary key.
I suppose you want to mutate the state of any DressingItem matching the criteria, in which case you have some options, all involving enumerating the resultset, and executing some behavior.
There is no LINQ operator to specifically do this, since LINQ operators are meant to be pure. Pure functions are functions that do not have side effects, and this is exactly what you are trying to do.
There is, however, an extensionmethod on List<T> which does allow this. e.g.
this.DressingItems.Where(di => di.DressingInfo.CatID == catId
&& di.ProductID == this.ProductID)
.ToList()
.ForEach(di =>
{
di.IsDefault = false
});
Or you could roll your own:
public static class EnumerableExtensions
{
public static IEnumerable<T> ForEach<T>(
this IEnumerable<T> source,
Action<T> mutator)
{
var buffered = source.ToList();
buffered.ForEach(mutator);
return buffered;
}
}
You might ask why the guys at Microsoft decided against adding this to the BCL: As I recall, the idea was that an extensionmethod vs. a foreach() { } construct would not yield much benefits in terms of typing anyway, and it wouldn't help at all in terms of ambiguity. All other operators are side-effect free, and this one is explicitely designed to induce them.
It is an InvalidOperationException thrown by the Single method.
The method is supposed to return only one element, please check the criteria that you use on your query.
However an exception is also thrown when it fails to find any element
you have more than one item in this.DressingItems that match the given CatId and Product Id.
if you are sure there must be one (single), then you have to review how is this.DressingItems loaded.
if it's expected there are more than one, then you have to use foreach to set the values.
Since you are looking for a one liner, you could create your own method doing that.
public static void DoActionForEachElement<T>(IEnumerable<T> items, Func<T, bool> predicate, Action<T> action)
{
foreach (var item in items)
{
if (predicate(item))
action(item);
}
}
and then call it by
DoActionForEachElement(
DressingItems,
xx => xx.DressingInfo.CatID == catId && xx.ProductID == ProductID,
x => x.IsDefault = false);
This way you don't have to cast the result from Where to a List first.
This code:
hub.MockedUserRepository.Setup(r => r.Update(It.IsAny<ControllUser>()))
.Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
.Verifiable();
Will print
NULL = True
So i am thinking using this matching will catch it:
var zombieDisconnectParameterMatcher = It.Is<ControllUser>(x => x.Zombies[0].ConnectionId == null);
hub.MockedUserRepository.Setup(r => r.Update(zombieDisconnectParameterMatcher))
.Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
.Verifiable();
But it does not.
Why?
By looking at the source code of It, it has to do with expression trees. I like the question; they can be quite puzzling. If you would take a look at the following method definitions:
public static TValue It.Is<TValue>(Expression<Func<TValue, bool>> match)
{
return Match<TValue>.Create(
value => match.Compile().Invoke(value),
() => It.Is<TValue>(match));
}
public static T Match.Create<T>(Predicate<T> condition, Expression<Func<T>> renderExpression)
{
// ...
return default(T);
}
If you would execute the following line:
var zombieDisconnectParameterMatcher = It.Is<ControllUser>(x => x.Zombies[0].ConnectionId == null);
Then It.Is<ControllUser>() will try to call a method called Match.Create<ControllUser>(), which returns the default of ControllUser. I assume ControllUser is a class and therefore zombieDisconnectParameterMatcher will be null. You should be able to see this with the debugger. So what actually you're calling is:
hub.MockedUserRepository.Setup(r => r.Update(null))
.Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
.Verifiable();
When executing the Update method with a non-null ControllUser (from the method that is being tested for example), the callback will not trigger. It simply doesn't match the criteria since it's not null. You would see the verification fail, also.
To resolve this issue, either inline the zombieDisconnectParameterMatcher variable, or make it an expression typed variable (eg. Expression<Func<...>>). The latter will make sure that the code is not executed, but treated as an expression which the mock framework can reason about ('is Update being called with Zombies[0].ConnectionId == null?').
It depends how the ControllUser instance is instantiated. If the instance that you refer to within the mock is not the actual instance referred to in the code under test, the Setup will fail. You will need to ensure that the instance of ControllUser referred to in the code under test is the same object as the one in the test code. If it isn't, you'll have to test for it using It.IsAny<ControllUser>() and a callback, as your first example shows. It's hard to say with certainty without seeing more of the code that you're testing.
Title kind of says it all. I just can't seem to find a DictionaryOrDefault \ ListOrDefault \ CollectionOrDefault option.
Is there such a method? If not how do I do this:
MyClass myObject = MyDictionary
.SingleOrDefault(x =>
{
if (x.Value != null)
return (x.Value.Id == sourceField.SrcField.Id);
else
return false;
}).Key;
if there is more than one match? (I am getting an execption because SingleOrDefault is only meant for single results (imagine that!).)
Guess I needed to be clearer (though the where answers looks good).
I have the above statement. I changed my program so that it does not always return 1 (there can be several values that match one key). That fails so I am looking for a collection to be returned (rather than just one item).
You can use IEnumerable<T>.FirstOrDefault(Func<T, bool> predicate) if your intention is to return the first one matching the predicate.
Otherwise you're simply looking at the IEnumerable<T>.Where(Func<T, bool> predicate) linq extension, which will return all elements that match the predicate passed. That will return an empty IEnumerable<T> if no elements match the predicate, at which point if you really need the value to be null, you can just look if anything is in it.
var res = MyDictionary.Where(x =>
{
if (x.Value != null)
return (x.Value.Id == sourceField.SrcField.Id);
return false;
});
if (!res.Any())
res = null;
Then if you absolutly need to have it as a list, you can just call
res.ToList();
Note that if you're actually manipulating a Dictionary<TKey, TValue>, res will contain KeyValuePair<TKey, TValue>'s.
if you do something like
var mylist = obj.Where(x=>x.attr1 == 4);
you can then check if anything was returned using the .Any() method
mylist.Any()