38

I recently had the opportunity to tweak some Java code and was able to take advantage of some new Java 8 features. In one particular case I needed to get a List of (String) .Name properties from a List of objects. A simplified example of what I did was:

// sample data: <Thing> objects have a single String property called "Name" 
List<Thing> thingList =
    new ArrayList<>(Arrays.asList(new Thing("Thing1"), new Thing("Thing2")));

// first pass
List<String> nameList = new ArrayList<>();
thingList.forEach(x -> nameList.add(x.getName()));

// refinement 1: use stream, map, and collect
List<String> nameList1 =
    thingList.stream().map(x -> x.getName()).collect(Collectors.toList());

// refinement 2: use "Thing::getName" method reference
List<String> nameList2 =
    thingList.stream().map(Thing::getName).collect(Collectors.toList());

I was curious to see how those approaches would translate to C#, and I got

// sample data: <Thing> objects have a single String property called "Name"
var thingList = new List<Thing> { new Thing("Thing1"), new Thing("Thing2") };

// first pass
var nameList = new List<String>();
thingList.ForEach(x => nameList.Add(x.Name));

// refinement 1: use Select and ToList
List<String> nameList1 = thingList.Select(x => x.Name).ToList();

What I haven't found (yet?) is a C# equivalent of "refinement 2" to replace the Lambda expression with something (a little bit) more concise. Is there a C# equivalent to the Java 8 "method reference" in this case, given that I'm trying to get a property of each object (which in Java is done using a getProperty method)?

Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
Gord Thompson
  • 116,920
  • 32
  • 215
  • 418

2 Answers2

12

You would have to declare a method outside of Thing (or a static Thing method), then you could pass a method-group reference to it:

private string GetName(Thing thing)
{
    return thing.Name;
}

...

List<String> nameList1 = thingList.Select(GetName).ToList();

In C# 6, you can also use an expression-bodied function to save a couple of lines:

private string GetName(Thing thing) => thing.Name;
Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
  • But `.Select(GetName)` is a syntax sugar that looks like a method reference, essentially it's still `.Select(x => GetName(x))`. – Cheng Chen May 12 '16 at 03:30
  • 1
    Pretty sure it's a method reference. But so what if it's sugar? OP just wants shorter code. What's the difference? – Blorgbeard May 12 '16 at 03:39
  • 8
    @Danny Chen: “essentially” Java 8’s method reference also is syntactic sugar for a lambda expression invoking the specified method. Though, technically, it’s the other way round, a lambda expression is syntactic sugar for a method reference to an additional method holding the lambda’s body. – Holger May 12 '16 at 08:42
7

C# has an equivalent feature called Method Group.

See more:
What is a method group in C#?

Sample:

private static int[] ParseInt(string s)
{
    var t = ParseString(s);
    var i = t.Select(x => int.Parse(x));
    return i.ToArray();
}

With metod group:

private static int[] ParseInt(string s)
{
    var t = ParseString(s);
    var i = t.Select(int.Parse);
    return i.ToArray();
}
Ola Ström
  • 4,136
  • 5
  • 22
  • 41
Adriano Moreira
  • 145
  • 2
  • 3