No definition for add in linq syntax? - c#

I was getting help related to a previous question but then told to ask a new question related to it but the code given I run into an error:
public void AddPersonToCommunity(string person, string communityName)
{
var result = communities.Where(n => String.Equals(n.CommunityName, communityName)).FirstOrDefault();
if (result != null)
{
result.Add(new Person() { PersonName = person }); //no definition for add?
}
}
You can see the previous question here for more specifics: relationships in rest?
If I do var result = communities; result will then have the definition for Add so im not sure whats going on?

You're calling Where() which will return an IEnumerable<Community> (no Add method) and then FirstOrDefault() which returns a Community (also no Add method). Where would you expect an Add method to come from?
I suspect you really want:
if (result != null)
{
result.People.Add(new Person { PersonName = person });
}
... because Community.People is a list of the people in that community, right?
Note that if you do var result = communities; there will indeed be an Add method - but with a signature of Add(Community), not Add(Person).
It's important that you keep the types of everything straight. This actually has very little to do with LINQ. You'd have seen the same result if you'd tried:
Community community = new Community();
community.Add(new Person { PersonName = person });

Adding onto #Jon's answer
There is a Concat extension method for IEnumerable<T> which allows you to logically combine two IEnumerable<T> objects into a single IEnumerable<T> which spans both collection. You could extend this logic to appending a single element and then apply that to your current situation.
public static IEnumerable<T> Concat(this IEnumerable<T> enumerable, T value) {
foreach (var cur in enumerable) {
yield return cur;
}
yield return value;
}
...
result = result.Concat(new Person() { PersonName = person });

Related

Yield keyword giving unexpected values for IEnumerable

This is my code (extension method)
public static IEnumerable<uint> GetFieldVals(this DataSource rs, IEnumerable<string> columnNames, Predicate<uint> shouldRun)
{
var rList = new List<uint>();
if (columnNames.Any())
foreach (var name in columnNames)
{
rs.GetFieldVal(name, out uint temp);
if (shouldRun(temp))
{
rList.Add(temp);
}
}
return rList;
}
This works. However, if I change it to this, the results are all the final item in the generated collection (although the Count is correct value).
public static IEnumerable<uint> GetFieldVals(this DataSource rs, IEnumerable<string> columnNames, Predicate<uint> shouldRun)
{
if (!columnNames.Any()) yield break;
foreach (var name in columnNames)
{
rs.GetFieldVal(name, out uint temp);
if (shouldRun(temp))
{
yield return temp;
}
}
}
What gives?
EDIT
Thank you everyone for your comments. I had written this in a bit of a hurry and then had a busy weekend, so I was unable to properly address this. I will do so now. You're all 100% correct that I left out too much.
I am attempting to take a clunky DataSource api and create an IEnumerable of valueobject items with it (which is easier and more flexible to work with). I am implementing this using a factory to keep it portable; my factory method implementation calls the code I wrote in my original post. This is a sample of what my valueobject looks like:
public class MyTableDataObject : IDataObject<uint>
{
public uint ID { get; set; }
public string Name { get; set; }
//MOAR properties
public IEnumerable<uint> SomeCollection { get; set; }
//MOAR properties
}
The issue I spoke about occurs when I have a collection of some type as a property in my valueobject (ie "SomeCollection" in the snippet above)
FWIW, here's my code for the collection of columnnames That I pass to the extension method from my original post.
public static IEnumerable<string> ColumnNames
{
get
{
yield return "COLUMNNAME00";
yield return "COLUMNNAME01";
yield return "COLUMNNAME02";
yield return "COLUMNNAME03";
yield return "COLUMNNAME04";
yield return "COLUMNNAME05";
yield return "COLUMNNAME06";
yield return "COLUMNNAME07";
yield return "COLUMNNAME08";
yield return "COLUMNNAME09";
yield return "COLUMNNAME10";
yield return "COLUMNNAME11";
yield return "COLUMNNAME12";
yield return "COLUMNNAME13";
yield return "COLUMNNAME14";
yield return "COLUMNNAME15";
}
}
Here is the calling code.
var rs = new DataSource();
rs.Open("Select * From MyTable");
//The Generic type on the enumerable indicates the type of the identifier of the items, not that the Enumerable is itself a list of uints. Do not get confused by this!
var dse = new DataSourceEnumerable<uint>(rs, new MyTableDataObjectFactory());
using (var writer = new MyWriterFacade("MyOutput.json"))
{
var json = new JsonSerializer(); //Newtonsoft.Json lib
var str = JsonConvert.SerializeObject(dse, Formatting.Indented);
writer.Write(str);
}
While the output json file's values are mostly correct, each "SomeCollection" has the same items in it (I believe it's the last item's SomeCollection values) when I use the yield keyword. When I don't use yield and use more traditional code, though, the json output illustrates the correct values for each SomeCollection in the file.
This is the code in the actual Enumerable:
public DataSourceEnumerable(DataSource ds, DataObjectFactory<T, DataSource> factory)
{
ds.MoveFirst();
innerList = new List<IDataObject<T>>();
_enumerator = Create(ds, factory, innerList);
}
public static IEnumerator<IDataObject<T>> Create(DataSource ds, DataObjectFactory<T, DataSource> factory,
IList<IDataObject<T>> innerList)
{
while (!ds.Eof)
{
innerList.Add(factory.InitializeDataObject<object, object>(ds));
ds.MoveNext();
}
return new DataSourceEnumerator(innerList);
}
I hope that sheds some light on it, if anyone can break that down for me a bit better. Appreciate it!
The only real difference in the code as shown relates to timing. With the list version, the operations are performed when the method is called. With the yield version, it is called later, when the result of the method is actually iterated.
Now: things can sometimes.change between calling a method that returns a sequence, and iterating that sequence. For example, the content of the data source or field sequence parameters could change. Or the logic of the predicate could change, usually due to "captured variables". So: the difference is in the code that calls this, which we can't see. But: look for timing between calling the method, and actually iterating over it (foreach etc).

C# - Make a generic foreach method that accepts any type?

Im busy updating an entity using entity framework and web api (on the PUT method of the controller). For each collection property on the updated object, I loop through and check if each item exists in the collection on the existing object or not. If not, I add it.
The trouble is I have a lot of collections on the object and I find myself repeating the following code many times over.
Is there a way for me to wrap this into a generic method and pass that method the 2 collections to compare? Maybe by specifying the name of the property to check and primary key? How would I be able to specify the type for the foreach loop for example?
foreach (HBGender gender in updated.HBGenders)
{
HBGender _gender = existing.HBGenders.FirstOrDefault(o => o.GenderID == gender.GenderID);
if (_gender == null)
{
//do some stuff here like attach and add
}
}
return existing; //return the modified object
Thanks in advance. I hope this makes sense.
In its simplest form you could write an extension method as such:
public static class IEnumerableExtensionMethods
{
public static ICollection<T> ForEachAndAdd<T>(this IEnumerable<T> self,
ICollection<T> other,
Func<T, T, bool> predicate) where T : class
{
foreach(var h1 in self)
{
if(other.FirstOrDefault(h2 => predicate(h1, h2)) == null)
other.Add(h1);
}
return other;
}
}
Usage:
List<HBGender> updated = new List<HBGender>();
List<HBGender> existing = new List<HBGender<();
return updated.ForEachAndAdd(existing, (h1, h2) => h1.Gender == h2.Gender);
Note that if there is extra logic needed during an add, you could add an additonal Action<T> parameter to do so.
I don't know what you are trying to do, but you can play with this example:
List<object> a = new List<object>();
a.Add("awgf");
a.Add('v');
a.Add(4);
foreach (object b in a)
{
Type type = b.GetType().//Select more usefull
Convert.ChangeType(object,type);
}
Just pass your existing check function, as an extra parameter
public List<Class1> Find(List<Class1> updated, List<Class1> existing, Func<Class1, bool> predicate)
{
foreach (Class1 gender in updated)
{
Class1 _gender = existing.FirstOrDefault(predicate); //predicate for quoted example will be o => o.GenderID == gender.GenderID
if (_gender == null)
{
//do some stuff here like attach and add
}
}
return existing;
}

Linq .SingleOrDefault - how to setup a default for a custom class?

i went over some questions and searched google a bit,
but i couldnt find an answer ( That satisfies me ).
Basicly, i understand the SingleOrDefault return null or 0 ( depends on the type ).
but how can i make it return something else ?
return myChannels.All.Where(_Channel => _Channel.Guid == this.ParentChannelGuid).SingleOrDefault(_SPECIFICCHANNEL);
so, i want _SPECIFICCHANNEL to be returned in case it is not single..
can that be done ?
You will have to make an extension method:
public static T SingleOr<T>(this IEnumerable<T> list, T defaultValue) where T : class
{
return list.SingleOrDefault() ?? defaultValue;
}
There is no other way. All classes default to null.
This can be accomplished in a rather simple way. If you create your own extension method that is more specific than the generic SingleOrDefault, then the compiler will prefer the more type-specific version. Here's an example that shows how to do that with a simple Person class (you can copy-paste it into LINQPad to quickly see the result):
public class Person
{
public string Name { get; set; }
public override string ToString()
{
return Name ?? "";
}
}
public static class PersonExtensionMethod
{
public static Person SingleOrDefault(this IEnumerable<Person> source)
{
var person = Enumerable.SingleOrDefault(source);
if (person == null)
return new Person { Name = "Unnamed" };
return person;
}
}
public static void Main()
{
var emptyCollection = new Person[0];
var nonEmptyCollection = new Person[] { new Person { Name = "Jack" } };
Debug.WriteLine("Empty collection: " + emptyCollection.SingleOrDefault());
Debug.WriteLine("Non-empty collection: " + nonEmptyCollection.SingleOrDefault());
}
In the above example, SingleOrDefault(IEnumerable<Person>), takes precedence over SingleOrDefault<T>(IEnumerable<T>) which is less specific.
Could you use DefaultIfEmpty() (psedo code follows) -
return myChannels.All.Where(_Channel => _Channel.Guid == this.ParentChannelGuid).DefaultIfEmpty(_SPECIFICCHANNEL).SingleOrDefault();
but how can i make it return something else ?
You cannot. You can make your own method — as shown by Oskar Kjellin — to return someting else, but SingleOrDefault will always behave as programmed, which means return the default value (null, 0) for an item.
Why not just use the "??" operator and say
return myChannels.SingleOrDefault(_Channel => _Channel.Guid == this.ParentChannelGuid) ??_SPECIFICCHANNEL;
You cannot define the default value of a type. It is always defined as null for reference types. For structs, it is an instance of the struct where all member fields in turn are set to their default values. For enums, it is always 0 (which may or may not be a defined value of the enum type in question)
Expanding on Oskar's answer of an extension method you can make that more generic so that it covers value as well as reference types with something like the below:
public static T SingleOrSpecifiedDefault<T>(this IEnumerable<T> enumerable, Expression<Func<T, bool>> singleOrDefault, T defaultValue) where T : IComparable
{
T singleValue = enumerable.SingleOrDefault(singleOrDefault.Compile());
if (singleValue == null || singleValue.CompareTo(default(T)) == 0)
{
return defaultValue;
}
return singleValue;
}
This allows you to specify the same LINQ expression that you'd use with SingleOrDefault as well as the defaultValue (which will be used if no match is found).

How to use LINQ to select all descendants of a composite object

How can I make ComponentTraversal.GetDescendants() better using LINQ?
Question
public static class ComponentTraversal
{
public static IEnumerable<Component> GetDescendants(this Composite composite)
{
//How can I do this better using LINQ?
IList<Component> descendants = new Component[]{};
foreach(var child in composite.Children)
{
descendants.Add(child);
if(child is Composite)
{
descendants.AddRange((child as Composite).GetDescendants());
}
}
return descendants;
}
}
public class Component
{
public string Name { get; set; }
}
public class Composite: Component
{
public IEnumerable<Component> Children { get; set; }
}
public class Leaf: Component
{
public object Value { get; set; }
}
Answer
I edited Chris's answer to provide a generic extension method that I've added to my Common library. I can see this being helpful for other people as well so here it is:
public static IEnumerable<T> GetDescendants<T>(this T component, Func<T,bool> isComposite, Func<T,IEnumerable<T>> getCompositeChildren)
{
var children = getCompositeChildren(component);
return children
.Where(isComposite)
.SelectMany(x => x.GetDescendants(isComposite, getCompositeChildren))
.Concat(children);
}
Thanks Chris!
Also,
Please look at LukeH's answer at http://blogs.msdn.com/b/wesdyer/archive/2007/03/23/all-about-iterators.aspx . His answer provides a better way to approach this problem in general, but I did not select it because it was not a direct answer to my question.
There are often good reasons to avoid (1) recursive method calls, (2) nested iterators, and (3) lots of throwaway allocations. This method avoids all of those potential pitfalls:
public static IEnumerable<Component> GetDescendants(this Composite composite)
{
var stack = new Stack<Component>();
do
{
if (composite != null)
{
// this will currently yield the children in reverse order
// use "composite.Children.Reverse()" to maintain original order
foreach (var child in composite.Children)
{
stack.Push(child);
}
}
if (stack.Count == 0)
break;
Component component = stack.Pop();
yield return component;
composite = component as Composite;
} while (true);
}
And here's the generic equivalent:
public static IEnumerable<T> GetDescendants<T>(this T component,
Func<T, bool> hasChildren, Func<T, IEnumerable<T>> getChildren)
{
var stack = new Stack<T>();
do
{
if (hasChildren(component))
{
// this will currently yield the children in reverse order
// use "composite.Children.Reverse()" to maintain original order
// or let the "getChildren" delegate handle the ordering
foreach (var child in getChildren(component))
{
stack.Push(child);
}
}
if (stack.Count == 0)
break;
component = stack.Pop();
yield return component;
} while (true);
}
var result = composite.Children.OfType<Composite>().SelectMany(child => child.GetDescendants()).Concat(composite.Children);
return result.ToList();
When doing a translation from imperitive syntax to LINQ, it is usually pretty easy to take the translation one step at a time. Here is how this works:
This is looping over composite.Children, so that will be the collection we apply LINQ to.
There are two general operations occuring in the loop, so lets do one of them at a time
The "if" statement is performing a filter. Normally, we would use "Where" to perform a filter, but in this case the filter is based on type. LINQ has "OfType" built in for this.
For each child composite, we want to recursively call GetDescendants and add the results to a single list. Whenever we want to transform an element into something else, we use either Select or SelectMany. Since we want to transform each element into a list and merge them all together, we use SelectMany.
Finally, to add in the composite.Children themselves, we concatenate those results to the end.
I don't know about better, but I think this performs the same logic:
public static IEnumerable<Component> GetDescendants(this Composite composite)
{
return composite.Children
.Concat(composite.Children
.Where(x => x is Composite)
.SelectMany(x => x.GetDescendants())
);
}
It might be shorter, but there is nothing wrong with what you have. As I said above, this is supposed to perform the same thing and I doubt that the performance of the function is improved.
This is a good example for when you might want to implement an iterator. This has the advantage of lazy evaluation in a slightly more readable syntax. Also, if you need to add additional custom logic then this form is more extensible
public static IEnumerable<Component> GetDescendants(this Composite composite)
{
foreach(var child in composite.Children)
{
yield return child;
if(!(child is Composite))
continue;
foreach (var subChild in ((Composite)child).GetDescendants())
yield return subChild;
}
}

How to check for nulls in a deep lambda expression? [duplicate]

This question already has answers here:
Possible pitfalls of using this (extension method based) shorthand
(11 answers)
Closed 9 years ago.
How can I check for nulls in a deep lamda expression?
Say for example I have a class structure that was nested several layers deep, and I wanted to execute the following lambda:
x => x.Two.Three.Four.Foo
I want it to return null if Two, Three, or Four were null, rather than throwing a System.NullReferenceException.
public class Tests
{
// This test will succeed
[Fact]
public void ReturnsValueWhenClass2NotNull()
{
var one = new One();
one.Two = new Two();
one.Two.Three = new Three();
one.Two.Three.Four = new Four();
one.Two.Three.Four.Foo = "blah";
var result = GetValue(one, x => x.Two.Three.Four.Foo);
Assert.Equal("blah", result);
}
// This test will fail
[Fact]
public void ReturnsNullWhenClass2IsNull()
{
var one = new One();
var result = GetValue(one, x => x.Two.Three.Four.Foo);
Assert.Equal(null, result);
}
private TResult GetValue<TModel, TResult>(TModel model, Expression<Func<TModel, TResult>> expression)
{
var func = expression.Compile();
var value = func(model);
return value;
}
public class One
{
public Two Two { get; set; }
}
public class Two
{
public Three Three { get; set; }
}
public class Three
{
public Four Four { get; set; }
}
public class Four
{
public string Foo { get; set; }
public string Bar { get; set; }
}
}
UPDATE:
One solution would be to catch the NullReferenceException like this:
private TResult GetValue<TModel, TResult>(TModel model, Expression<Func<TModel, TResult>> expression)
{
TResult value;
try
{
var func = expression.Compile();
value = func(model);
}
catch (NullReferenceException)
{
value = default(TResult);
}
return value;
}
But I hate to incur the expense of catching an exception that is not, in my mind, exceptional. I expect this to be the case quite often in my domain.
UPDATE 2:
Another solution would be modify the property getters like this:
public class One
{
private Two two;
public Two Two
{
get
{
return two ?? new Two();
}
set
{
two = value;
}
}
}
Which is mostly ok for my domain, but there are times when I really to expect a property to return null. I checked the answer from Josh E as helpful since it comes pretty close to what I need in some cases.
You could do this with a generic helper extension method, something like:
public static class Get {
public static T IfNotNull<T, U>(this U item, Func<U, T> lambda) where U: class {
if (item == null) {
return default(T);
}
return lambda(item);
}
}
var one = new One();
string fooIfNotNull = one.IfNotNull(x => x.Two).IfNotNull(x => x.Three).IfNotNull(x => x.Four).IfNotNull(x => x.Foo);
You can't do that in a concise way. You can either make the lambda multiple lines, or use nested ternary operators:
var result = GetValue(one, x => x.Two == null ? null :
x.Two.Three == null ? null :
x.Two.Three.Four == null ? null :
x.Two.Three.Four.Foo;
Ugly, I know.
Doing this concisely requires an as-yet-unimplemented operator. We considered adding an operator ".?" to C# 4.0 which would have your desired semantics, but unfortunately it did not fit into our budget. We'll consider it for a hypothetical future version of the language.
You can now do using the Maybe project on codeplex.
Syntax is:
string result = One.Maybe(o => o.Two.Three.Four.Foo);
string cityName = Employee.Maybe(e => e.Person.Address.CityName);
I've written an extension method which enables you to do this:
blah.GetValueOrDefault(x => x.Two.Three.Four.Foo);
It uses Expression Trees to build a nested conditional checking for nulls at each node before returning the expression value; the created expression tree is compiled to a Func and cached, so subsequent uses of the same call should run at almost native speed.
You can also pass in a default value to return if you like:
blah.GetValueOrDefault(x => x.Two.Three.Four.Foo, Foo.Empty);
I've written a blog about it here.
I'm not skilled in c#, but maybe there's some way to implement the "andand" pattern from ruby that solves exactly this problem without polluting the implementation.
The concept is also known as the Maybe Monad in Haskell.
The title of this article seems promising.
Always initialize your properties before using them. Add a constructor to class One, Two, Three and Four. In the constructor initialize your properties so they are not null.
You could modify your getters to read something like:
private Two _two;
public Two Two
{
get
{
if (null == _two)
return new Two();
else
return _two;
}
}
I find the coalesce operator useful for this at times. This only helps though if there is a default/null equivalent version of the object you can drop in.
For instance, sometimes when I'm cracking open XML...
IEnumeratable<XElement> sample;
sample.Where(S => (S.Attribute["name"] ?? new XAttribute("name","")).Value.StartsWith("Hello"))...
Depending on how the default objects are retrieved this can be verbose, and the above example is not a great use but you get the idea. For the particular case of reading XML attributes I have an extension method that returns the attribute value or an empty string.
I converted a function that used a lot of if statements to avoid the nulls to the .IFNotNull method for classes that I converted from an XSD that are 4 and 5 levels deep.
Here are a few lines of the converted code:
ProdYear.PRIOR_CUMULATIVE_CARBON_DIOXIDE_VALUE = year.IfNotNull(x => x.PRIOR_CUMULATIVE).IfNotNull(y => y.CARBON_DIOXIDE).IfNotNull(z => z.VALUE).ToDouble();
ProdYear.PRIOR_CUMULATIVE_CARBON_DIOXIDE_UOM = year.IfNotNull(x => x.PRIOR_CUMULATIVE).IfNotNull(y => y.CARBON_DIOXIDE).IfNotNull(z => z.UOM);
Here are some interesting stats about it:
1) This new method took 3.7409 times longer to run that the variation with the If Statements.
2) I decreased my function line count from 157 to 59.
3) CodeRush from DevExpress has a "Maintenance Complexity" score. When I converted to the Lambda statements, it increased from 984 to 2076, which is theoretically much harder to maintain.

Categories