tags:

views:

277

answers:

7

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 ?

A: 

No, there is not.

Richard J. Ross III
+1  A: 

The closest you're going to get is anonymous types like you'd see in a LINQ expression. A short example from the link:

var v = new { Amount = 108, Message = "Hello" };

Definitely not what you're looking for. I haven't heard of future support for anonymous classes in C# either.

David Hoerster
+11  A: 

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...

Jon Skeet
I have found out that maybe I cannot use this solution for my original problem (besides of the theoretical discusion in comments). Please check my third EDIT in original question - description of the problem was just too long to write it in comment. I hope that my explanation there can be understand. Thank you
drasto
@drasto: Answer edited too. Hope this helps.
Jon Skeet
Thanks. Anything else would be uglier than this. So I'm going to do it this way.
drasto
+2  A: 

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.

Ben Robinson
OK so what do I do ? Do I have to create new class for this ? Is there any other way(delegates, labda expressions or whatever) ?
drasto
I would say jon skeet's `ProjectionEqualityComparer` class is your best bet.
Ben Robinson
A: 

You could define the implementation of the interface in one place, 1 class, map the interface to your desired implementation class in your favorite IOC framework and not have to think about instantiating a 1-time-use anonymous implementation at all.

Tahbaza
+2  A: 

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.

munificent
-1 Shorter, but also completely broken - because you don't override GetHashCode. Moreover, you *can't* override GetHashCode when only provided with a `Func<T, T, bool>` unless the override just returns 0.Will happily reverse the downvote if you implement something that works... but you'll need a `Func<T, int>` as well... or something like my `ProjectionEqualityComparer` (which I personally view as somewhat cleaner, but obviously I'm biased).
Jon Skeet
@Jon Skeet: You have already suggested solution that came to my mind: constructor would take 2 parameters, fist one stays unchanged, second would be of type `Func<T, int>` and it would be used in `GetHashCode`.You may be right that `ProjectionEqualityComparer` is little bit cleaner but it removes some variability - sometimes you may want to use say 3 properties in for equality comparison but only 2 of them in would be used in GetHashCode. So I prefer this solution (just with GetHashCode added). +1 for nice idea
drasto
@drasto: I'd say that increases the chance of making a mistake - in particular, while using 3 properties for equality and 2 for the hashcode is valid (although it gives a crummy hash), using 2 properties for equality and 3 for the hashcode would be invalid, but not *obviously* so. Can you think of a situation where that's *actually* what you'd want to do? I'd rather go for a solution which applies to the 99% case and is simpler to get right than something more flexible but harder to use. Note that with a projection you only specify one thing, and that only deals with one object. (Continued.)
Jon Skeet
Using the "two function" version here, the hash code generation would only have to deal with one object, but the comparison has to deal with two - you get the redundancy of specifying `Name` and `Id` twice *and* you then have to get the hashing function right, taking into account the possibility of `Name` being null etc. Is the added complexity *really* worth the flexibility you're unlikely ever to need?
Jon Skeet
Again, you might be right. However I can think of a case when I would want to use only some properties (from the set of properties that define equality) in GetHashCode. This might be the case when one of properties is array or collection that you need to iterate and test equality element after element. Lets say that you know that the array or collection can by long and the other properties will most likely difference not equal objects. (continue)
drasto
@Jon Skeet: In such rare case you will want to have this array or collection in equality comparison (as the last property to compare) but in in hash code generation - from performance reasons. Maybe I could make up some other cases (but the practise can surely create much more then me :) ) but you are right that they are very rare. I'm not sure if additional flexibility is worth risking possible mistake. Maybe it's just that I like lambda expressions and I like to have control over code (and I don't know anything about anonymous types and how they equality works - and that may also change ?).
drasto
@drasto: If you're *only* testing for equality then there's no harm in making `GetHashCode` use all the fields... if it's not being called, who cares? Just testing Equals isn't going to call `GetHashCode`. Again, you end up with simpler code by using a projection. Of course, if you *do* ever need the extra flexibility, you can use something like this... but why not just use the simplest approach that works until you've got more complex requirements? As for anonymous types changing equality behaviour: it's guaranteed by the spec.
Jon Skeet
Note that even in some case where `GetHashCode` *was* being used time and time again, it would be *very* unusual for this to actually end up being a performance bottleneck. If it did, it could be worth implementing the interface yourself anyway, to avoid the delegate call. You *have* control over the code, of course... you can abandon the simple solution for a more complex one any time you want. Why pick the most complex solution *first* though?
Jon Skeet
@Jon Skeet: I was not quite clear. All the time I'm thinking about the use of `IEqualityComparer` in terms of using it in hash table like collection(for example that Dictionary). In that case GetHashCode is always called on each object that is added to the collection. However equality of objects is tested only sometimes. So creating hash code is more performance critical then equality testing. That's why I wrote that you might want to skip some properties from hash code generation when it would take long time to generate their hash code but you always want to add them in equality testing.
drasto
Jon Skeet: Anyway you are probably right in everything else (about preferring simpler approach). Thank you a lot for consultation.
drasto
You're totally right Jon. I forgot about `GetHashCode` completely in my five-minutes answer. Thanks for bringing that up!
munificent
+1  A: 

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()
    {
        // ...
    }
}
Dr. Wily's Apprentice
In my case I consider this the best solution (it's clean and quick, partial classes are really made for this purpose...). Accepted.
drasto