Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的匿名内部类?_C#_Java_Syntax - Fatal编程技术网

C#中的匿名内部类?

C#中的匿名内部类?,c#,java,syntax,C#,Java,Syntax,在C#中是否有类似于匿名内部类(在Java中使用)的东西 我举例说明我将如何使用它:我正在声明和初始化类型为IDictionary的字段,我需要编写自定义IEqualityComparer。这是因为我希望当两个人的名字和ID(而不是默认情况下的ID)相等时,IDictionary将他们视为平等的。我不需要这个IEqualityComparer代码中的任何其他地方 所以我必须声明实现IEqualityComparer的新类才能做到这一点吗?在Java中,我会使用匿名类,类似这样的东西(这是混合C#

在C#中是否有类似于匿名内部类(在Java中使用)的东西

我举例说明我将如何使用它:我正在声明和初始化类型为
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()
    {
        // ...
    }
}