等效于 C# 中的 Java 匿名类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27273328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Equivalent of Java's anonymous class in C#?
提问by bkjvbx
I am trying to port an SDK written in java to C#.
我正在尝试将用 Java 编写的 SDK 移植到 C#。
In this software there are many "handler" interfaces with several methods (for example: attemptSomethingHandler
with success()
and several different failure methods). This interface is then implemented and instantiated anonymously within the calling class and passed to the attemptSomething
method of the SomethingModel
class. This is an async method and has several places where it could fail or calls another method (passing on the handler). This way, the anonymous implementation of attemptSomethingHandler
can reference private methods in the class that calls attemptSomething
.
在这个软件中有许多“处理程序”接口和几种方法(例如:attemptSomethingHandler
withsuccess()
和几种不同的故障方法)。然后在调用类中匿名实现和实例化该接口,并传递给该类的attemptSomething
方法SomethingModel
。这是一个异步方法,有几个地方可能会失败或调用另一个方法(传递处理程序)。这样, 的匿名实现attemptSomethingHandler
就可以引用调用 的类中的私有方法attemptSomething
。
In C# it is not possible to anonymously implement an interface. I could explicitly implement a new class, but this implementation would be unique to this calling class and not used for anything else. More importantly, I would not be able to access the private methods in the calling class, which I need and do not want to make public.
在 C# 中,不可能匿名实现接口。我可以显式地实现一个新类,但是这个实现对于这个调用类来说是唯一的,不用于其他任何东西。更重要的是,我将无法访问调用类中的私有方法,而我需要且不想公开这些方法。
Basically, I need to run different code from the calling class depending on what happens in the SomethingModel
class methods.
基本上,我需要根据SomethingModel
类方法中发生的情况从调用类运行不同的代码。
I've been reading up on delegates but this would require passing as many delegates as there are methods in the handler interface (as far as I can tell). What is the appropriate way to do this in C#? I feel like I'm missing out on a very common programming strategy. There simply must be an easy, clean way to structure and solve this problem.
我一直在阅读委托,但这需要传递与处理程序接口中的方法一样多的委托(据我所知)。在 C# 中执行此操作的适当方法是什么?我觉得我错过了一个非常常见的编程策略。必须有一种简单、干净的方法来构建和解决这个问题。
采纳答案by Dan Pantry
In C#, we don't have anonymous types like Java per se. You can create an anonymous type which contains fields like so:
在 C# 中,我们没有像 Java 本身那样的匿名类型。您可以创建一个包含如下字段的匿名类型:
var myObject = new { Foo = "foo", Bar = 1, Quz = 4.2f }
var myObject = new { Foo = "foo", Bar = 1, Quz = 4.2f }
However these cannot have methods placed in them and are only passable into methods by use of object
or dynamic
(as they have no type at compile-time, they are generated by the compiler AFAIK)
但是,这些不能在其中放置方法,只能通过使用object
or传递给方法dynamic
(因为它们在编译时没有类型,它们由编译器 AFAIK 生成)
Instead in C# we use, as you said, delegates or lambdas.
正如您所说,在 C# 中,我们使用委托或 lambdas。
If I understand your pickle correctly, you couldimplement a nested private class like so:
如果我正确理解你的泡菜,你可以实现一个嵌套的私有类,如下所示:
interface IMyInterface
{
void Foo();
}
class MyClass
{
public void Bar()
{
var obj = new MyInterface();
obj.Foo();
}
private class MyInterface : IMyInterface
{
public void Foo()
{
// stuff
}
}
}
Now MyClass
can create an instance of MyInterface
which implements IMyInterface
. As commentors have mentioned, MyInterface
can access members of MyClass
(although you most certainly want to try and stick to using publicly accessible members of both types).
现在MyClass
可以创建一个MyInterface
实现的实例IMyInterface
。正如评论者所提到的,MyInterface
可以访问的成员MyClass
(尽管您肯定想尝试并坚持使用这两种类型的可公开访问的成员)。
This encapsulates the "anonymous" class (using Java terms here to make it simpler) and also means that you could potentially return MyInterface
as an IMyInterface
and the rest of the software would be none the wiser. This is actually how some abstract factory patterns work.
这封装了“匿名”类(在此使用 Java 术语使其更简单),也意味着您可能会MyInterface
作为 an返回,IMyInterface
而软件的其余部分也不会更聪明。这实际上是一些抽象工厂模式的工作方式。
Basically, I need to run different code from the calling class depending on what happens in the SomethingModel class methods.
基本上,我需要根据SomethingModel 类方法中发生的情况从调用类运行不同的代码。
This smells of heavy coupling. Oh dear!
这闻起来有重耦合的味道。哦亲爱的!
It sounds to me like your particular problem could use refactoring. In C# you canuse Events to solve this (note: Can, not should). Just have an Event for each "branch" point of your method. However I must say that this does make your solution harder to envisage and maintain.
在我看来,您的特定问题可以使用重构。在 C# 中,您可以使用事件来解决这个问题(注意:可以,不应该)。只需为您的方法的每个“分支”点设置一个事件。但是我必须说,这确实使您的解决方案更难设想和维护。
However I suggest you architect your solution in a way such that you don't need such heavy coupling like that.
但是,我建议您以一种不需要如此繁重的耦合的方式构建您的解决方案。
You could also try using a Pipeline model but I'm not sure how to implement that myself. I know that jetty (or is it Netty? the NIO for Java by JBOSS) certainly used a similar model.
您也可以尝试使用管道模型,但我不确定如何自己实现。我知道码头(或者是 Netty?JBOSS 的 Java 版 NIO)肯定使用了类似的模型。
You may find that throwing out some unit tests in order to test the expected functionality of your class will make it easier to architect your solution (TDD).
您可能会发现,为了测试类的预期功能而放弃一些单元测试将使构建解决方案 (TDD) 变得更加容易。
回答by GvS
Using delegates:
使用委托:
void AttemptSomethingAsync(Action onSuccess, Action<string> onError1, Action onError2 = null) {
// ...
}
// Call it using:
AttemptSomethingAsync(onSuccess: () => { Yes(); }, onError1: (msg) => { OhNo(msg); });
Or, using a class
或者,使用类
class AttemptSomethingHandler {
Action OnSuccess;
Action<string> OnError1;
Action OnError2;
}
void AttemptSomethingAsync(AttemptSomethingHandler handler) {
// ...
}
// And you call it like
AttemptSomethingAsync(new AttemptSomethingHandler() {
OnSuccess = () => { Yes() };
});
Or events
或活动
public delegate void SuccessHandler();
public delegate void ErrorHandler(string msg);
class SomethingModel {
public event SuccessHandler OnSuccess;
public event ErrorHandler OnError1;
public void AttemptSomethingAsync() {
// ...
}
}
// Use it like
var model = new SomethingModel();
model.OnSuccess += Yes;
model.AttemptSomethingAsync();
private void Yes() {
}
回答by weston
You can use nested classes to simulate anonymous classes, but in order to use nested classes in the same way as Java you will need to pass a reference to the outer class. In Java all nested and anonymous classes have this by default, and only static ones do not.
您可以使用嵌套类来模拟匿名类,但为了以与 Java 相同的方式使用嵌套类,您需要传递对外部类的引用。在 Java 中,默认情况下所有嵌套和匿名类都有这个,只有静态类没有。
interface IMyInterface
{
void Foo();
}
class MyClass
{
public void Bar()
{
IMyInterface obj = new AnonymousAnalog(this);
obj.Foo();
}
private class AnonymousAnalog : IMyInterface
{
public void Foo(MyClass outerThis)
{
outerThis.privateFieldOnOuter;
outerThis.PrivateMethodOnOuter();
}
}
...
}