2

I'm working on translating some code from Java to C# but am having some trouble, maybe someone out there can help?

I have problems trying to replicate anonymous interface implementations that are widely used in Java, but have no idea how to.

An example is:

List<DATA> queue1 = new ArrayList<DATA>(dataSet);
            // Sort by distance to the first promoted data
            Collections.sort(queue1, new Comparator<DATA>() {
                @Override
                public int compare(DATA data1, DATA data2) {
                    double distance1 = distanceFunction.calculate(data1, promoted.first);
                    double distance2 = distanceFunction.calculate(data2, promoted.first);
                    return Double.compare(distance1, distance2);
                }
            });


  • 1) What have you tried? 2) What is promoted.first? 3) What are you trying to do in this code? - IronMan84
  • One substantial difference is that classes are anonymous in Java, but methods are anonymous in C#. The answers below are good - just keep in mind that if you see Java code implementing an interface with more than one member, it's up to you whether the corresponding anonymous methods (i.e., delegates) are in the same class or not. - prprcupofcoffee

5 답변


5

I have problems trying to replicate the inline functions that are widely used in Java

These are not inline functions, that's anonymous classes implementing a specific interface.

C# provides delegates that you can define inline or in a separate function.

Here is an example of sorting a List<DATA> in place using the Comparison<T> delegate:

List<DATA> queue = new List<DATA>();
queue.Sort(
    (left, right) => {
        double distance1 = distanceFunction.Calculate(left, promoted.first);
        double distance2 = distanceFunction.Calculate(right, promoted.first);
        return Double.Compare(distance1, distance2);
    }
);

Note that in order for this to work, the distanceFunction variable needs to be in scope at the spot where you invoke queue.Sort. It can be a local variable defined above the invocation point, or a member variable/property of the class enclosing the function that makes the call.


  • +1. It's also worth noting that C# doesn't allow for non-static inner classes either, for the same reasons it doesn't allow for anonymous classes. - Brian
  • @Brian: What do you mean with "non-static inner classes" not being allowed? The following is valid code: public class Outer { private class Inner { } } - Daniel Hilgarth
  • But Inner is always static in C#. That is, it doesn't have an implicit reference to Outer. The reference has to be explicitly specified via a field in the inner class. In fact, the implicit reference in Java in non-static inner classes and anonymous classes is often the source of memory leaks in Java code. - Brian
  • @DanielHilgarth Ah, a difference in semantics then. By static I meant in reference to the class declaration, not its methods. What I meant is private class Inner in C# is the same as private static class Inner in Java. In any case, still a good answer. - Brian
  • @DanielHilgarth What Java calls a static inner class and what C# calls a static class are two very different things: in C# you can instantiate only non-static classes, and IIRC nested classes cannot be static at all. In Java, static member classes are identical to C#'s nested classes, while non-static member classes retain a reference to the object inside of which they were instantiated. There is no analog in C#, but you can easily emulate it by keeping a reference to Outer instance inside the Inner object, and setting the reference to Outer in the Inner's constructor. - dasblinkenlight

1

In C# you end up using delegates instead of interfaces in may cases, especially in cases like this where it's likely the caller will want to define the method inline. You can use a lambda to define an anonymous method inline where any delegate is expected.

List<String> list = new List<String> { "B", "D", "E" };

list.Sort((a, b) => a.CompareTo(b));

There is no equivalent to Java's anonymous interface implementations in C#, so if there is an interface required (which isn't the case for sorting a List) you'll need to create a named class to implement it.


0

C# uses the concept of delegates in the place of anonymous interface implementations.

Assuming you've replaced ArrayList<DATA> with the .Net List<DATA>:

IEnumerable<DATA> sorted =
    queue1.OrderBy(q => distanceFunction.calculate(q, promoted.first));


0

assume that you have an a List of Data objects in c#:

queue1.OrderBy(a => distanceFunction.Calculate(a, promoted.First));


  • Note that here you aren't mutating the list, you're creating a new collection based on the previous one. You would need to use List.Sort to mutate the list itself. - Servy

0

If you want something that parallels the original Java, then:

internal virtual void test()
{
    List<int> queue1 = new List<int>(dataSet);
    queue1.Sort(new ComparatorAnonymousInnerClassHelper());
}

private class ComparatorAnonymousInnerClassHelper : IComparer<int>
{
    public virtual int compare(int data1, int data2)
    {
        double distance1 = distanceFunction.calculate(data1, promoted.first);
        double distance2 = distanceFunction.calculate(data2, promoted.first);
        return distance1.CompareTo(distance2);
    }
}


  • That's not an anonymous interface implementation, or an anonymous anything... - Servy
  • This is the C# equivalent. Why do you feel that it needs to be called 'anonymous'? - Dave Doknjas
  • There is no exact C# equivalent; there is no mechanism in C# for creating anonymous interface implementations. The closest mechanism, that is the mechanism generally used in place of that the OP is using in Java, is anonymous methods, rather than named interface implementations. - Servy
  • If you try it out, you'll see that it works identically - this just explicitly does what Java does behind the scenes. - Dave Doknjas
  • Yes - I agree. However, I look at it from a code conversion perspective - given an anonymous interface implementation in Java, the most pain-free way of getting the same result in C# is making the hidden implementing class non-anonymous. - Dave Doknjas

Linked


Related

Latest