我知道它可以用Java完成,因为我过去曾广泛使用过这种技术。 Java中的一个例子如下所示。 (附加问题。这种技术被称为什么?如果没有名称,很难找到这样的例子。)
public abstract class Example {
public abstract void doStuff();
}
public class StartHere{
public static void main(string[] args){
Example x = new Example(){
public void doStuff(){
System.out.println("Did stuff");
}
};
x.doStuff();
}
}
现在,我的主要问题是,这也可以在C#中完成,如果是的话,怎么做?
答案 0 :(得分:21)
Java技术称为“Anonymous inner class”,C#中没有等效技术。
答案 1 :(得分:17)
使用lamba表达式和类初始值设定项,您可以通过一些努力获得相同的行为。
public class Example {
public Action DoStuff;
public Action<int> DoStuffWithParameter;
public Func<int> DoStuffWithReturnValue;
}
class Program {
static void Main(string[] args) {
var x = new Example() {
DoStuff = () => {
Console.WriteLine("Did Stuff");
},
DoStuffWithParameter = (p) => {
Console.WriteLine("Did Stuff with parameter " + p);
},
DoStuffWithReturnValue = () => { return 99; }
};
x.DoStuff();
x.DoStuffWithParameter(10);
int value = x.DoStuffWithReturnValue();
Console.WriteLine("Return value " + value);
Console.ReadLine();
}
}
我刚刚意识到这个解决方案的一个问题是,如果要在Example类中创建字段,lambda表达式将无法访问这些字段。
但是,没有理由不能将Example实例传递给lambda表达式,这样可以让他们访问示例可能包含的任何公共状态。 AFAIK在功能上等同于Java匿名内部类。
P.S。如果你要投票给答案,请帮我们一个忙,并添加评论,说明你不同意的原因: - )
答案 2 :(得分:10)
通常,使用.Net中的委托以更清晰的方式解决使用Java中的匿名内部类解决的问题。您的示例有点过于简单,无法确定您的意图。如果您使用抽象类的意图是传递“行为”,那么请考虑仅使用Action
委托。
public class StartHere{
public static void main(string[] args){
Action doStuff = () => Console.WriteLine("Did stuff");
executeSomething(doStuff);
}
public static void executeSomething(Action action)
{
action();
}
}
答案 3 :(得分:8)
在C#中无法做到;你需要声明一个新的类类型。你在C#中最接近的可能是一个命名的嵌套类:
public class StartHere{
private class Foo : Example {
public override void doStuff()
{
Console.WriteLine("did stuff");
}
}
public static void Main(string[] args){
Example x = new Foo();
x.doStuff();
}
}
答案 4 :(得分:1)
这在C#中是不受支持的,如果它由我决定也不应该如此。
java中内部类的增加主要是由于缺少C#所具有的委托或lambdas。因此,虽然这种类型的功能目前是java中的“唯一希望”,但您通常可以在C#中使用其他机制来实现相同的目的。在这方面,Java就像用一只手弹钢琴一样。
(不可否认,我们很多人都非常擅长这种单手游戏;现在看来我们必须至少等到java 8才能关闭......)
答案 5 :(得分:1)
虽然所有答案都很好,但大多数建议依赖于C#3.0
因此,为了完整起见,我将添加另一个既不使用lambdas也不使用Func类型的解决方案(当然,正如Matt Olenik在评论中提到的那样,可以概括下面的代表以相同的方式工作。)。对于那些可能仍在使用C#2.0的人。也许不是最好的解决方案,但它确实有效。
public class Example
{
public delegate void DoStuffDelecate();
public DoStuffDelecate DoStuff;
public delegate void DoStuffWithDelecate(int n);
public DoStuffWithDelecate DoStuffWithParameter;
public delegate int DoStuffWithReturnDelecate();
public DoStuffWithReturnDelecate DoStuffWithReturnValue;
}
class Program
{
static int MethodWithReturnValue()
{
return 99;
}
static void MethodForDelecate()
{
Console.WriteLine("Did Stuff");
}
static void MethodForDelecate(int n)
{
Console.WriteLine("Did Stuff with parameter " + n);
}
static void Main(string[] args)
{
var x = new Example();
x.DoStuff = MethodForDelecate;
x.DoStuffWithParameter = MethodForDelecate;
x.DoStuffWithReturnValue = MethodWithReturnValue;
x.DoStuff();
x.DoStuffWithParameter(10);
int value = x.DoStuffWithReturnValue();
Console.WriteLine("Return value " + value);
Console.ReadLine();
}
}
答案 6 :(得分:1)
由于您的类只代表一个操作,您可以在您的情况下使用委托,有一个现有的委托:
public delegate void Action();
这与你的班级完全相同。
你的匿名课程的宣言更加清晰:
Action action = () => Console.WriteLine("Hello world");
action(); // invoke
你甚至可以使用闭包:
public void Hello(string name)
{
Action action = () => Console.WriteLine("Hello " + name);
action(); // will call the above lambda !
}
答案 7 :(得分:0)
简而言之,您必须将其定义为单独的子类。我认为这个功能即将推出C#4.0?
编辑:不,它不会来C#4.0我做到了。
答案 8 :(得分:0)