C#中的匿名内部类?
在C#中是否有类似于匿名内部类(在Java中使用)的东西 我举例说明我将如何使用它:我正在声明和初始化类型为C#中的匿名内部类?,c#,java,syntax,C#,Java,Syntax,在C#中是否有类似于匿名内部类(在Java中使用)的东西 我举例说明我将如何使用它:我正在声明和初始化类型为IDictionary的字段,我需要编写自定义IEqualityComparer。这是因为我希望当两个人的名字和ID(而不是默认情况下的ID)相等时,IDictionary将他们视为平等的。我不需要这个IEqualityComparer代码中的任何其他地方 所以我必须声明实现IEqualityComparer的新类才能做到这一点吗?在Java中,我会使用匿名类,类似这样的东西(这是混合C#
IDictionary
的字段,我需要编写自定义IEqualityComparer
。这是因为我希望当两个人的名字和ID(而不是默认情况下的ID)相等时,IDictionary将他们视为平等的。我不需要这个IEqualityComparer
代码中的任何其他地方
所以我必须声明实现IEqualityComparer
的新类才能做到这一点吗?在Java中,我会使用匿名类,类似这样的东西(这是混合C#-Java语法,只是为了显示我想要的功能):
其中,Color
是从数据库生成的另一个类(实体)
这是颜色的属性:
Id:int
Alpha:byte
Red:byte
Green:byte
Blue:byte
所以我不能修改字体,也不能修改颜色(如果我不想在每次更改数据库时一遍又一遍地重写这些更改),我想要的是拥有这本词典
:
private IDictionary<Font, Something> cache = new Dictionary<Font, Something>(new SomeEqualityComparer());
我猜匿名类型在调用它们的
Equals(object)
时,会对所有属性调用Equals(object)
。但是,由于我无法覆盖Color
的Equals(object)
,因此它不会按照我的需要比较Color
s(使用Id
之外的所有属性),因此Font
s的相等性也会被错误地测试。我说得对吗?不,在这个问题最初写出来的时候(C#3.0),还没有。你将得到的最接近的结果就像你在LINQ表达式中看到的一样。链接中的一个简短示例:
var v = new { Amount = 108, Message = "Hello" };
绝对不是你想要的。我也没有听说将来会支持C#中的匿名类。我有一个
ProjectionQualityComparer
类,你可以在其中使用。您将使用如下代码:
IEqualityComparer<Person> comparer = ProjectionEqualityComparer<Person>.Create
(p => new { p.Name, p.Id });
如果您能够在属性方面修改颜色
类型,那么如果您可以给它一个从其他属性生成的ARGB属性,则会更简单,这样您就可以编写:
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 });
专用IDictionary缓存=新字典
(ProjectionQualityComparer.Create(f=>new{
f、 字体名称,f.大小,f.粗体,f.斜体,f.下划线,f.删除,
f、 Foreground.ARGB});
这很难看,但应该可以用…不,没有。有匿名类型,例如
var MyType = new { id=1, name="john", dept = "sales" };
但是它们非常有限,只包含只读属性,不包含任何方法。您可以在一个位置1类中定义接口的实现,将接口映射到您喜爱的IOC框架中所需的实现类,而不必考虑实例化一次性匿名实现。字面上的答案是没有,C#没有匿名的内部类,因为Java添加这些类是为了解决C#没有的一流函数的不足。更具体地说,为了解决您的问题,您可以在
Person
类上实现IEquatable
,然后IDictionary
将自动使用它。这是这个问题最常见的解决方案,只要您同意比较被烘焙到该类中的人员的过程,它就会起作用
如果希望比较/相等逻辑不直接绑定到人员
,则.NET中的大多数集合允许您传入比较
对象(这是一个委托,而不是一个接口),这样您就可以很好地执行就地排序逻辑。例如,要按姓名对人员列表进行排序,您可以执行以下操作:
List<Person> people = ...
people.Sort((x, y) => x.Name.CompareTo(x.y));
但是,每次需要比较时,都必须定义一个新类,这是一件烦琐的事情。我要做的是创建一个具有函数的通用类:
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;
}
公共类相等:相等比较
{
公共平等(功能比较)
{
this.comparer=比较器;
}
公共覆盖布尔等于(TA,TB)
{
返回比较器(a,b);
}
专用函数比较器;
}
添加一个小助手类:
public static class Equality
{
public static Equality<T> Create<T>(Func<T, T, bool> comparer)
{
return new Equality<T>(comparer);
}
}
公共静态类相等
{
公共静态相等创建(Func比较器)
{
返回新的等式(比较器);
}
}
然后您的解决方案变成:
IDictionary<Person, Account> myDict = new Dictionary<Person, Account>(
Equality.Create((a, b) => a.Id == b.Id && a.Name == b.Name);
IDictionary myDict=新词典(
创建((a,b)=>a.Id==b.Id&&a.Name==b.Name);
甚至比Java中的代码还要短。在上一次编辑中,您提到不实现Equals和GetHashCode的原因是,类的代码是自动生成的,您不希望每次重新生成代码时都重新实现该代码 这是其中一种情况 许多代码生成工具都会生成带有partial关键字的类,以允许您利用该功能。请检查为代码生成的类是否为partial 在重新生成代码时不会被覆盖的单独文件(或多个文件)中,在同一程序集中,可以有如下内容:
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()
{
// ...
}
}
好的,那我该怎么办?我必须为此创建新类吗?还有其他方法(委托、labda表达式或其他任何方法)吗?我想说jon skeet的
ProjectionQualityComparer
类是你最好的选择。-1更短,但也完全坏了-因为你不重写GetHashCode。此外,如果只提供Func
,你就不能重写GetHashCode,除非重写只返回0。如果你实现了某些东西,你会很高兴地逆转否决票ng这是可行的…但是你也需要一个函数
…或者类似我的ProjectionQualityComparer
(我个人认为这有点干净,但显然我有偏见)@Jon Skeet:您已经提出了我想到的解决方案:构造函数将使用两个参数,第一个参数保持不变,第二个参数的类型为Func
,它将用于GetHashCode
。您可能是对的,ProjectionQualityComparer
稍微干净一点,但它删除了一些参数
public class PersonComparer : EqualityComparer<Person>
{
public override bool Equals(Person a, Person b)
{
return a.Id == b.Id && a.Name == b.Name;
}
}
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;
}
public static class Equality
{
public static Equality<T> Create<T>(Func<T, T, bool> comparer)
{
return new Equality<T>(comparer);
}
}
IDictionary<Person, Account> myDict = new Dictionary<Person, Account>(
Equality.Create((a, b) => a.Id == b.Id && a.Name == b.Name);
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()
{
// ...
}
}