0

There have been times where I've had functionality I wanted to share with EF LINQ commands, and also in different places when dealing with just a single object in memory. Being able to share an expression in these two instances could be useful as to not duplicate logic.

Below I've got a dummy example where in a deliberately roundabout way I use an expression on a single object, but I was wondering if there is a sensible, succinct and clean way to just directly apply an expression to an object, or are expressions designed to be used explicitly in LINQ collection situations?

//Silly non practical example to show LINQ working
public static void Main(string[] args)
{
    const string testString = "Test";
    var length = testString.SingleSelect(GetCount);
    Console.WriteLine(length);
}

private static T2 SingleSelect<T1, T2>(this T1 input, Expression<Func<T1, T2>> expression)
{
    return new List<T1> { input }.AsQueryable().Select(expression).First();
}

private static Expression<Func<string, int>> GetCount => input => input.Length;
Geesh_SO
  • 2,156
  • 5
  • 31
  • 58
  • The idea of using expressions only to directly apply it to an object sounds weird to me. As far as I know an expression is used when you're interested in the how and what is happening, but directly applying means you're just interested in the result so the added functionality of an expression seems wasted. –  Oct 30 '19 at 10:10
  • That was the sense that I got, but I was hoping there would be a way that I could achieve it sensibly/correctly so I could share a single piece of logic cleanly when for example doing operations on EF db sets, and also a single object of the same model which I have in memory. Maybe having two fields, one for the actual function (to be used as normal on single objects), and the other with an expression wrapping the function when doing EF operation on large sets is a way to go, I'm not sure. – Geesh_SO Oct 30 '19 at 10:22
  • Voted to close as dupe of https://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct which has a ton of answers covering how awesome expressions are. – Ian Kemp Oct 30 '19 at 10:55

1 Answers1

0

You may use

private static T2 SingleSelect<T1, T2>(this T1 input, Expression<Func<T1, T2>> expression)
{
    return expression.Compile()(input);
}

But there will be a difference to EF LINQ - EF LINQ will execute most of the logic on the DB side (e.g. on SQL Server). But here expression.Compile()(...) will be executed on your program side, that is .net code by CLR.

Renat
  • 7,718
  • 2
  • 20
  • 34
  • That's quite a bit cleaner, thanks. In this instance where I'm dealing with single objects already in memory, and expressions that normally deal with primitive fields (should also be in memory), I think despite losing LINQ-to-SQL I'd be okay performance wise here. Primarily I just don't want to duplicate the logic. – Geesh_SO Oct 30 '19 at 10:33
  • @Geesh_SO Make sure you only call `.Compile()` once and you cache the result. – canton7 Nov 01 '19 at 09:00