Reputation: 3271
I'm fairly new to using linq expressions and trying to refactor some old code. Is there a way to turn the following method into a short and clean Linq expression?
public int GetParentCount(object o)
{
int count = 0;
object parent = GetParentObject(o);
while (parent != null)
{
count++;
parent = GetParentObject(parent);
}
return count;
}
I've tried searching but got no satisfying results
Upvotes: 4
Views: 797
Reputation: 3489
Here's a generic function that can work on any type of object, with any object name containing the parent (uses Func<T,T>
):
public static class MyExtensions {
/// <summary>Gets an enumerable of all ancestors.</summary>
public static IEnumerable<T> Ancestors<T>(this T obj, Func<T, T> expr) where T : class {
obj = expr.Invoke(obj);
while(obj != null) {
yield return obj;
obj = expr.Invoke(obj);
}
}
Here's an example application that uses the function:
class MyClass {
public MyClass Parent { get; set; }
}
void Main()
{
MyClass a = new MyClass();
a.Parent = new MyClass();
a.Parent.Parent = new MyClass();
a.Ancestors(myObj => myObj.Parent).Count(); // Result: 2
}
Upvotes: 0
Reputation: 109567
And as an alternative to Ander's solution, a non-recursive approach:
using System;
using System.Linq;
using System.Collections.Generic;
namespace Demo
{
static class Program
{
static void Main()
{
var obj = new object();
int count = AllParents(obj).Count(); // Using Linq only here.
Console.WriteLine(count);
}
public static IEnumerable<object> AllParents(object obj)
{
while (true)
{
obj = GetParentObject(obj);
if (obj == null)
yield break;
yield return obj;
}
}
// This is merely a hacky test implementation.
public static object GetParentObject(object obj)
{
if (--count == 0)
return null;
return obj;
}
private static int count = 10;
}
}
Upvotes: 1
Reputation: 11101
You can enumerate the ancestors like so:
public IEnumerable<MyClass> AncestorsOf(MyClass obj)
{
var parent = GetParentObject(obj);
if (parent != null)
{
yield return parent;
foreach(var grandparent in AncestorsOf(parent))
yield return grandparent;
}
}
Getting the total count would then be a simple AncestorsOf(obj).Count()
Upvotes: 2