How do I pass a Linq query to a method? - c#

I'd like to pass a Linq query to a method, how do I specify the argument type?
My link query look something like:
var query =
from p in pointList
where p.X < 100
select new {X = p.X, Y = p.Y}
clearly I'm new to Linq, and will probably get rid of the receiving method eventually when I convert the rest of my code, but it seems like something I should know...
thanks

You'll need to either use a normal type for the projection, or make the method you're passing it to generic as well (which will mean you can't do as much with it). What exactly are you trying to do? If you need to use the X and Y values from the method, you'll definitely need to create a normal type. (There are horribly hacky ways of avoiding it, but they're not a good idea.)
Note: some other answers are currently talking about IQueryable<T>, but there's no indication that you're using anything more than LINQ to Objects, in which case it'll be an IEnumerable<T> instead - but the T is currently an anonymous type. That's the bit you'll need to work on if you want to use the individual values within each item. If you're not using LINQ to Objects, please clarify the question and I'll edit this answer.
For example, taking your current query (which is slightly broken, as you can't use two projection initializers twice with the same name X). You'd create a new type, e.g. MyPoint
public sealed class MyPoint
{
private readonly int x;
private readonly int y;
public int X { get { return x; } }
public int Y { get { return y; } }
public MyPoint(int x, int y)
{
this.x = x;
this.y = y;
}
}
Your query would then be:
var query =
from p in pointList
where p.X < 100
select new MyPoint(p.X, p.Y);
You'd then write your method as:
public void SomeMethod(IEnumerable<MyPoint> points)
{
...
}
And call it as SomeMethod(query);

I think what you are looking for is the Expression class. For instance,
public void DoSomething()
{
User user = GetUser(x => x.ID == 12);
}
IQueryable<User> UserCollection;
public User GetUser(Expression<Func<User,bool>> expression)
{
return UserCollection.expression;
}

public void DoSomething(IQueryable query) { ... }
public void DoSomething<T>(IQueryable<T> query) { ... }
And just in case (if you will need passing expressions):
public void DoSomething(Expression exp) { ... }

While both tvanfosson and Jon are correct, you can just write your function to accept an IEnumerable<T> (you can either make your function generic or you can specify the specific concrete generic version you want, which is more likely the correct option) as LINQ to Objects produces an IEnumerable<T> and LINQ to SQL produces an IQueryable<T>, which implements IEnumerable<T>. This option should allow you to be source-agnostic.

you can also use the below code:
IEnumerable <TableName> result = from x in dataBase.TableName
select x;
methodName(result);
private void methodName (IEnumerable<TableName> result)
{
codes.....
}

Related

Find matching element in list using delegate and lambda

Edit
My original question was not very clear, so I'd like to try to rephrase it now. Please let me know if I still miss the mark.
Essentially, I'm trying to return a new string, in which all substrings enclosed by brackets have been replaced by a string from an object in a list. As an abstract example, I want to do something like the following:
public class MyType () : IEquatable <Property>
{
public string id;
public override String ToString()
{
return id;
}
public bool Equals ( MyType other )
{
if ( other is MyType == false )
{
return false;
}
return this.id == other.id;
}
}
List<MyType> listOfCustomTypes = new List<MyType> ();
return Regex.Replace ( originalString, "{(.*?)}", d => listOfCustomTypes.Where ( t => t.id == d.Groups[1].Value ).FirstOrDefault ());
The problem I've run into, or, error, specifically, is Cannot convert lambda expression to delegate type (System.Text.RegularExpressions.MatchEvaluator) because some of the return types in the block are not implicitly convertible to the delegate return type.
I am assuming that it isn't allowed to use return types in delegates, or something, because I can normally access it's properties, or cast to string.
I've probably still managed to jumble my question, so if it helps, my full project can be seen here, and the relevant file for this question is here (specific line is 161).
Original Question
I'm trying to learn how to use delegates and lambdas, and in typical fashion, bit off more than I can chew. In the following code snippet, I define a class, which holds a list of classes. In another function, I'm trying to use a string to find a list item, and get a value from that item.
[XmlRoot ( "Replacers" )]
public class Replacers
{
[XmlElement ( "Property" )]
public List<Property> properties = new List<Property> ();
[XmlIgnore]
public static Replacers replacers;
}
public class Property : IEquatable <Property>
{
[XmlAttribute ( "id" )]
public string id;
[XmlElement ( "Value" )]
public List<Value> propertyValue = new List<Value> ();
public override String ToString()
{
return id;
}
public bool Equals ( Property other )
{
return this.id == other.id && this.propertyValue == other.propertyValue;
}
}
public static class GetVariable
{
public static string FromUser ( string originalString )
{
try
{
//return Regex.Replace ( originalString, "{(.*?)}", m => Replacers.replacers.properties.FindIndex ( m.Groups[1].Value ) );
} catch ( Exception e )
{
return "ERROR: Unable to find '" + Regex.Match ( originalString, "{(.*?)}" ) + "'";
}
}
}
The commented out line above is that I'm trying to figure out. How do I replace anything that matches the pattern {(.*?)} with a value from the list item of the same name.
Thanks for taking the time to consider my question!
TL;DR:
How do I iterate over a list using lambda, where the iteration returns the actual list item? As an example, I want to do something like: Regex.Replace ( input, pattern, m => myList.Where(listItem.identifier == m). I don't feel like I've made my question very clear, so please ask, if you're confused. Thank you!
Consider this example:
var foos = new[] { "aaa", "aba", "aca" };
var bars = foos.Where(f => f.Contains("b")).Select(f => Regex.Replace(f, "b", "d"));
foreach (var bar in bars)
Console.WriteLine(bar);
// Output:
ada
Edit: I'll try to address your comment
A lambda is just a shorthand for a delegate (a typed-method).
You're probably accustomed to types like int, string, double, Animal, etc.
Well, just extend that notion to method signatures.
You can think of any method signature as being a type.
Here's a method that returns a bool, and takes an int as a parameter:
bool A(int i) { ... }
So the signature can be viewed as a type.
A lambda is a shorthand for this. Here's a lambda, that takes an int, and returns a bool, just like the method signature above:
(x) => x % 2 == 0
Linq extension methods (Where(), Select(), etc) all take some delegate type, or lambda expression.
myCollection.Where(x => x % 2 == 0).Where(x => x > 10).Select(x => x * 2);
The beauty is you can keep chaining these extension methods, each one becoming an additional filter if you will.
Select() is special because it's a projection operation (it transforms the items in the collection). You can see it takes this odd parameter here:
Func<string, string> // or something like that, depends on the types in your collection
A Func is kinda like a delegate, but in a more generic sense. It's easy to understand. The first type arguments are the input parameters (think parameters of a method), and the last is the output (think the return type of a method)
Func<in, in, in, out>
Consider this:
// Here's a method signature
bool MyMethod(int a, int b)
// Here's a lambda of the same delegate type
(a, b) => a == b
// Here's a Func being assigned that lambda
Func<int, int, bool> func = (a, b) => a == b;

How to mix monadic constructs in a single Linq expression?

I have a toy implementation of a Maybe monad in C# and have implemented the relevant SelectMany extension methods to work with Linq. I stumbled upon a problem when I tried to mix IEnumerable and IMaybe in a single Linq statement.
The Maybe monad looks like
public interface IMaybe<T>
{
bool HasValue { get; }
T Value { get; }
}
public static class Maybe
{
class SomeImpl<T>: IMaybe<T> // obvious implementation snipped for brevity
class NoneImpl<T>: IMaybe<T> // obvious implementation snipped for brevity
// methods to construct the Maybe monad
public static Wrap<T> Some<T>(T value);
public static Wrap<T> Some<T>(T? value) where T: struct;
public static IMaybe<T> None<T>();
public static IMaybe<B> SelectMany<A, B>(this IMaybe<A> a, Func<A, IMaybe<B>> mapFn)
{
if (a.HasValue)
return mapFn(a.Value);
else
return None<B>();
}
public static IMaybe<C> SelectMany<A, B, C>(
this IMaybe<A> a, Func<A, IMaybe<B>> mapFn, Func<A, B, C> selector)
{
if (a.HasValue)
{
var b = mapFn(a.Value);
if (b.HasValue)
return Some(selector(a.Value, b.Value));
else
return None<C>();
}
else
return None<C>();
}
}
My program tries to read a file, parse the content into a number of URI entries, and for each of the entries download the content from the URI. Exactly how these operations are implemented is irrelevant. The trouble I have lies in the chaining these operations in a Linq statement. I.e.
static IMaybe<string> ReadFile(string path);
static IMaybe<KeyValuePair<string, Uri>[]> ParseEntries(string input);
static IMaybe<string> Download(Uri location);
static void Main(string[] args)
{
var result = // IEnumerable<IMaybe<anonymous type of {Key, Content}>>
from fileContent in ReadFile(args[0])
from entries in ParseEntries(fileContent)
from entry in entries // this line won't compile
from download in Download(entry.Value)
select new { Key = entry.Key, Content = download };
// rest of program snipped off for brevity
}
The error in question complains about mixing the IMaybe and IEnumerable monads. In its exact wording:
Error 1 An expression of type 'System.Collections.Generic.KeyValuePair[]' is not allowed in a subsequent from clause in a query expression with source type 'MonadicSharp.IMaybe'. Type inference failed in the call to 'SelectMany'. C:\Dev\Local\MonadicSharp\MonadicSharp\Program.cs 142 31 MonadicSharp
How do I get around this?
It seems to me that the issue lies in the signature for ParseEntries.
It currently is:
static IMaybe<KeyValuePair<string, Uri>[]> ParseEntries(string input);
Perhaps it should be?
static IMaybe<KeyValuePair<string, Uri>>[] ParseEntries(string input);
So instead of a maybe of array it should be an array of maybe.
I think the issue is because entries is of type IMaybe<T> and not of type IEnumerable<T>.
Have you tried something like this:
from entry in entries.Value
Of course this is not what the purpose of a Monad is, but this should be the first step.
After some research I've concluded that it is just impossible to mix monads in a single LINQ statement so I decided to break it into two statements. This is how it works:
First off, I need to make a slight change to the IMaybe interface declaration to use covariance:
public interface IMaybe<out T>{ ... }
Next, I need some helper method to transform the IMaybe monad to the IEnumerable monad:
public static IEnumerable<IMaybe<T>> UnfoldAll<T>(
this IMaybe<IEnumerable<T>> source)
{
if (source.HasValue)
return Enumerable.Range(0, 1).Select(i => Maybe.None<T>());
else
return source.Value.Select(value => Maybe.Some(value));
}
And finally, I will break the original LINQ statement into two statements (nesting LINQ expressions works too)
static void Main(string[] args)
{
var path = args[0];
var theEntries =
from fileContent in ReadFile(path)
from entries in ParseEntries(fileContent)
select entries;
var theContents =
from entry in theEntries.UnfoldAll()
where entry.HasValue
select Download(entry.Value.Value);
foreach (var content in theContents)
{
//...
}
}
As you can see, the first LINQ statement works on IMaybe monad and the second one on the IEnumerable.

How can I make a monoid-like interface in C#?

I want to require things which implement an interface (or derive from a class) to have an implementation for Aggregate included. That is, if they are of type T I want them to have something of type Func<T,T,T>. In Haskell this is called a "monoid".
EDIT: What I want to call is something like this:
list.Aggregate((x, accum) => accump.MAppend(x));
Based on DigalD's answer, this is my best attempt, but it doesn't compile:
interface IMonoid<T>
{
T MAppend(T other);
}
class Test
{
public static void runTest<T>(IEnumerable<IMonoid<T>> list)
{
// doesn't work
list.Aggregate((x, ac) => ac.MAppend(x));
}
}
A monoid is an associative operation together with an identity for that operation.
interface Monoid<T> {
T MAppend(T t1, T t2);
T MEmpty
}
The contract of a monoid is that for all a, b, and c:
Associativity: MAppend(Mappend(a, b), c) = MAppend(a, Mappend(b, c))
Left identity: MAppend(MEmpty, a) = a
Right identity: MAppend(a, MEmpty) = a
You can use it to add up the elements in a list:
class Test {
public static T runTest<T>(IEnumerable<T> list, Monoid<T> m) {
list.Aggregate(m.MEmpty, (a, b) => m.MAppend(a, b));
}
}
The answer by Apocalisp looks closest to the mark, but I'd prefer something like this:
public interface IMonoid<T>
{
T Combine(T x, T y);
T Identity { get; }
}
While Haskell calls the monoid identity mempty, I think it's more reasonable to use the language of abstract algebra, so I named the identity value Identity. Likewise, I prefer the term Combine over Haskell's mappend, because the word append seems to indicate some sort of list append operation, which it doesn't have to be at all. Combine, however, isn't a perfect word either, because neither the first nor the last monoids combine the values; instead, they ignore one of them. I'm open to suggestions of a better name for the binary operation...
(In Haskell, BTW, I prefer using the <> operator alias instead of the mappend function, so that sort of side-steps the naming issue...)
Using the above IMonoid<T> interface, you can now write an extension method like this:
public static class Monoid
{
public static T Concat<T>(this IMonoid<T> m, IEnumerable<T> values)
{
return values.Aggregate(m.Identity, (acc, x) => m.Combine(acc, x));
}
}
Here, I completely arbitrarily and inconsistently decided to go with Haskell's naming, so I named the method Concat.
As I describe in my article Monoids accumulate, one always has to start the accumulation with the monoidal identity, in this case m.Identity.
As I describe in my article Semigroups accumulate, instead of an imperative for loop, you can use the Aggregate extension method, but you'll have to use the overload that takes an initial seed value. That seed value is m.Identity.
You can now define various monoids, such as Sum:
public class Sum : IMonoid<int>
{
public int Combine(int x, int y)
{
return x + y;
}
public int Identity
{
get { return 0; }
}
}
or Product:
public class Product : IMonoid<int>
{
public int Combine(int x, int y)
{
return x * y;
}
public int Identity
{
get { return 1; }
}
}
Since I made the monoid argument the this argument of the Concat method, the method extends the IMonoid<T> interface, rather than IEnumerable<T>. I think this gives you a more readable API. For example:
var s = new Sum().Concat(new[] { 1000, 300, 30, 7 });
produces s == 1337, while
var p = new Product().Concat(new[] { 2, 3, 7 });
produces p == 42.
If you don't like having to create a new Sum() or new Product() object every time, you can make your monoids Singletons, like this All monoid:
public class All : IMonoid<bool>
{
public static All Instance = new All();
private All() { }
public bool Combine(bool x, bool y)
{
return x && y;
}
public bool Identity
{
get { return true; }
}
}
which you can use like this:
var a = All.Instance.Concat(new[] { true, true, true });
Here, a is true. You can use a similarly written Any monoid in the same way:
var a = Any.Instance.Concat(new[] { false, true, false });
I'll leave it as an exercise for the reader to figure out how Any is implemented.
What about this version:
interface IMonoid<T>
{
T MAppend(IMonoid<T> other);
}
class Test
{
public static void runTest<T>(IEnumerable<IMonoid<T>> list)
where T : IMonoid<T>
{
list.Aggregate((x, ac) => ac.MAppend(x));
}
}
Or better yet, enforcing it from the start:
interface IMonoid<T>
where T : IMonoid<T>
{
T MAppend(IMonoid<T> other);
}
Shouldn't you just make the Interface generic as well?
interface IMonoid<T>
{
public IMonoidHandler<T> handler {get;set;}
}

Passing lambda expression as parameter

I've got a few tables that all have the same column domainID which basically just controls what data gets displayed on which website, as they share a database.
So when I go to databind a table to a control I would need to create a large switch to handle the different LINQ queries. I would like to create a utility method which takes the table type as a parameter and then return a where clause based on a column in passed table.
public static IEnumerable<T> ExecuteInContext<T>(
IQueryable<T> src)
{
int domain = 1;//hard coded for example
return src.Where(x => x.DomainID == domain);//Won't work, has to be a way to do this.
}
I'm stuck on the return code. You can't simply construct a where clause like I currently am because it doesn't know what table i'm talking about.
I'm trying to call that first method like this:
using (DataClasses1DataContext db = new DataClasses1DataContext())
{
var q = Utility.ExecuteInContext(db.GetTable<item>());
Repeater1.DataSource = q;
Repeater1.DataBind();
}
I hope this explains what I'm trying to do.
Edit: BrokenGlass's answer solved my problem. I would like to add that you need to open up your .dbml.cs file and extend the table/class with your interface. I also wanted to point out that the project wouldn't build if my column was nullable, it said it wasn't the same return type as my interface.
You have to restrict your T to a class that has a property of DomainID - you can add these interface implementations in partial classes that extend your data model.
public interface IFoo
{
int DomainId { get; set; }
}
..
public static IQueryable<T> ExecuteInContext<T>(IQueryable<T> src) where T: IFoo
{
int domain = 1;//hard coded for example
return src.Where(x => x.DomainID == domain);
}
Expression pe = Expression.Parameter(typeof(T));
Expression prope = Expression.Property(pe, "DomainID");
Expression ce = Expression.Equals(prope,
Expression.Constant((int)1);
Expression<Func<T,bool>> exp =
Expression.Lambda<Func<T,bool>>(
ce, pe);
return query.Where(exp);
You should be able to cast your generic parameter to the intended type...
public static IEnumerable<T> ExecuteInContext<T>(IQueryable<T> src)
{
int domain = 1;//hard coded for example
return src.Where(x => ((T)x).DomainID == domain);
}
But you realize you've created a generic method that assumes its type parameter will always expose a specific property? If you're going to do that, you should apply a generic type constraint such that T is always derived from a type that has that property...
For example:
public static IEnumerable<T> ExecuteInContext<T>(IQueryable<T> src) where T : IMyDomainObject
I'm not sure if I understand what you mean, but maybe you want to add a where clause:
public static IEnumerable<T> ExecuteInContext<T>(IQueryable<T> src)
where T: MyType //MyType exposing your DomainId
{
int domain = 1;//hard coded for example
return src.Where(x => x.DomainID == domain);//Won't work, has to be a way to do this.
}

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