Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous inner classes in C#?

Tags:

java

syntax

c#

Is there something like anonymous inner classes (used in Java) in C#?

I explain what I would use it for by example: I'm declaring and initializing field of type IDictionary<Person, Account> and I need to write custom IEqualityComparer<Person>. That is because I want two Persons to be treated as equal by the IDictionary when they have equal names and IDs (not only IDs as it is by default). I will not need this IEqualityComparer<Person> anywhere else in the code.

So I do I have to declare new class that implements IEqualityComparer<Person> to do this ? In Java I would use anonymous class, something like this(this is mixed C#-Java syntax, just to show what functionality I'm looking for):

IDictionry<Person, Account> myDict = new Dictionary<Person, Account>(
    new IEqualityComparer<Person>(){
        public bool Equals(Person a, Person b){
            return a.Id == b.Id && a.Name == b.Name;
        }

        public int GetHashCode(Person p){
            return p.Id.GetHashCode() * p.Name.GetHashCode();
        }
    });

Is something like this in C# ? I'm too lazy to write new class every time I need something like this.

Note: This is syntax question. I know how to write it, but I want to know if it's possible to make the code shorter.

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

EDIT: How do you yourself code similar cases ? Do you create new class to implement the interface or what do you do ? Maybe you have some trick that I might like.

EDIT What about future support for anonymous classes like those in Java ? Have you heard something about it ?

EDIT: Well I see I'll have to provide my actual code - not just an example. That's because I don't know if it's going to work with Jon's Skeet's solution.

The actual reason why I don't just implement Equals(object) and GetHashCode in the class itself is, that it's class(entity) generated by E-R framework from model diagram. If I implemented it in class itself my code would be deleted from the class(entity) every time I update the model from database (using "update from database" feature). The class is actually called Font not Person. It has this properities:

Id: int
FamilyName:string
Size:int
Bold:bool
Italic:bool
Underlined:bool
Striked:bool
Foreground:Color

Where Color is another class (entity) generated from database.

This are properties of Color:

Id:int
Alpha:byte
Red:byte
Green:byte
Blue:byte

So I cannot modify Font, neither Color (if I don't want to rewrite those changes over and over again every time I change database) What I want is to have this Dictionary:

private IDictionary<Font, Something> cache = new Dictionary<Font, Something>(new SomeEqualityComparer());

And the comparer SomeEqualityComparer should ensure that two Fonts would be considered equal if and only if all the properties listed above(except Id) are equal. In the case of last property Foreground two Colors are considered equal when all their properties(except Id) are equal.

Now if I use solution that Jon Skeet has kindly recommended me, I'm not sure if that can be ensured. If I used something like:

private IDictionary<Font, Something> cache = new Dictionary<Font, Something>(ProjectionEqualityComparer<Font>.Create
(f => new { f.FontName, f.Size, f.Bold, f.Italic, f.Underlined, f.Striked, f.Foreground});

I'd guess that anonymous types call Equals(object) on all properties when their Equals(object) is called. However as I cannot override Color's Equals(object) it would not compare Colors as I want (using all properties except Id) so also the equality of Fonts would be tested incorrectly. Am I right ?

like image 442
Rasto Avatar asked Aug 22 '10 20:08

Rasto


People also ask

What are anonymous inner classes?

It is an inner class without a name and for which only a single object is created. An anonymous inner class can be useful when making an instance of an object with certain “extras” such as overriding methods of a class or interface, without having to actually subclass a class.

What are anonymous classes?

A nested class that doesn't have any name is known as an anonymous class. An anonymous class must be defined inside another class. Hence, it is also known as an anonymous inner class. Its syntax is: class outerClass { // defining anonymous class object1 = new Type(parameterList) { // body of the anonymous class }; }

What is true about anonymous inner class?

1. Which is true about an anonymous inner class? A. It can extend exactly one class and implement exactly one interface.

What are anonymous classes used for?

Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.


4 Answers

I have a ProjectionEqualityComparer class you could use in MiscUtil. You'd use code like this:

IEqualityComparer<Person> comparer = ProjectionEqualityComparer<Person>.Create
    (p => new { p.Name, p.Id });

Thhat uses the fact that anonymous types have appropriate equality notions built in - when the ProjectionEqualityComparer is asked to compare two people for equality, it will project each to the anonymous type, and compare those instances. Likewise when it's asked for a hashcode, it will perform the projection and ask that for its hash code.

EDIT: To tackle your colour problem, you're right: if Color doesn't override Equals/GetHashCode in the way that you want, you can't use it directly. However, you can do this instead:

private IDictionary<Font, Something> cache = new Dictionary<Font, Something>
   (ProjectionEqualityComparer<Font>.Create(f => new { 
        f.FontName, f.Size, f.Bold, f.Italic, f.Underlined, f.Striked, 
        f.Foreground.Alpha, f.Foreground.Red, f.Foreground.Green,
        f.Foreground.Blue});

If you're able to modify the Color type in terms of properties, it would be simpler if you could give it an ARGB property generated from the others, so you could write:

private IDictionary<Font, Something> cache = new Dictionary<Font, Something>
   (ProjectionEqualityComparer<Font>.Create(f => new { 
        f.FontName, f.Size, f.Bold, f.Italic, f.Underlined, f.Striked, 
        f.Foreground.ARGB });

That's pretty ugly, but it should work...

like image 131
Jon Skeet Avatar answered Sep 19 '22 15:09

Jon Skeet


In your last edit you mention that the reason that you don't implement Equals and GetHashCode is because the code for your classes is auto-generated and you don't want to have to re-implement that code each time you regenerate the code.

That's one of the scenarios for which partial classes were introduced in C#

A lot of code generation tools will generate classes with the partial keyword to allow you to take advantage of that feature. Check if the classes that are being generated for your code are partial.

In a separate file (or files) that won't be overwritten when you regenerate the code, within the same assembly, you could have something like the following:

partial class Font
{
    public override bool Equals(object obj)
    {
        // ...
    }

    public override int GetHashCode()
    {
        // ...
    }
}

partial class Color
{
    public override bool Equals(object obj)
    {
        // ...
    }

    public override int GetHashCode()
    {
        // ...
    }
}
like image 36
Dr. Wily's Apprentice Avatar answered Sep 19 '22 15:09

Dr. Wily's Apprentice


No there isn't. There are anonymous types e.g.

var MyType = new { id=1, name="john", dept = "sales" };

but they are very limited, and only contain read only properties and no methods.

like image 38
Ben Robinson Avatar answered Sep 19 '22 15:09

Ben Robinson


The literal answer is that no, C# doesn't have anonymous inner classes, because Java added those to get around its lack of first-class functions, which C# does have. More specifically, to solve your problem, you can just implement IEquatable<Person> on your Person class, and then IDictionary will use that automatically. That's the most common solution to this problem and works as long as your OK with the process for comparing Persons being baked into that class.

If you want the comparison/equality logic to not be tied directly to Person, most collections in .NET allow you to pass in a Comparison<T> object (which is a delegate, not an interface), letting you do nice in-place sorting logic. For example, to sort a list of people by name, you could do:

List<Person> people = ...
people.Sort((x, y) => x.Name.CompareTo(x.y));

Unfortunately, Dictionary doesn't have something similar to an equality function. In .NET 4.0, the stock answer seems to be to override EqualityComparer<T>:

public class PersonComparer : EqualityComparer<Person>
{
    public override bool Equals(Person a, Person b)
    {
        return a.Id == b.Id && a.Name == b.Name;
    }
}

Having to define a new class each time you need to compare, though, is a chore. What I'd do is make a generic one that takes a function:

public class Equality<T> : EqualityComparer<T>
{
    public Equality(Func<T, T, bool> comparer)
    {
        this.comparer = comparer;
    }

    public override bool Equals(T a, T b)
    {
        return comparer(a, b);
    }

    private Func<T, T, bool> comparer;
}

Add a little helper class:

public static class Equality
{
    public static Equality<T> Create<T>(Func<T, T, bool> comparer)
    {
        return new Equality<T>(comparer);
    }
}

And then your solution becomes:

IDictionary<Person, Account> myDict = new Dictionary<Person, Account>(
    Equality.Create((a, b) => a.Id == b.Id && a.Name == b.Name);

Even shorter than it would be in Java.

like image 25
munificent Avatar answered Sep 19 '22 15:09

munificent