繁体   English   中英

C#:在不定义新类的情况下创建抽象类的实例

[英]C#: Creating an instance of an abstract class without defining new class

我知道它可以用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#中完成,如果是这样,怎么样?

Java技术被称为“ 匿名内部类 ”,在C#中没有等价物。

使用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表达式将无法访问这些字段。

但是,没有理由不能将示例实例传递给lambda表达式,这将使它们可以访问示例可能包含的任何公共状态。 AFAIK在功能上等同于Java匿名内部类。

PS如果你要投票给答案,请帮我们一个忙,并添加评论,说明你不同意的原因:-)

通常,使用.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();
   }
}

这不能在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();
   }
}

这在C#中是不受支持的,如果它由我决定,它也不应该如此。

java中内部类的增加主要是由于缺少C#所具有的委托或lambdas。 因此,虽然这种类型的功能目前是java中的“唯一希望”,但您通常可以在C#中使用其他机制来实现相同的目的。 在这方面,Java就像用一只手弹钢琴一样。

(不可否认,我们很多人都非常擅长这种单手游戏;现在好像我们必须至少等到java 8才能关闭......)

虽然所有好的答案,但大多数建议都依赖于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();
    }
}

由于您的类只代表一个操作,您可以在您的情况下使用委托,有一个现有的委托:

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 !
}

简而言之,您必须将其定义为单独的子类。 我认为这个功能即将推出C#4.0?

编辑:不,它不会来C#4.0我做到了。

你可以通过Mocking in .NET来实现这一目标。 但是,对于此功能没有语言支持,我认为它将在C#4.0中提供。 有许多图书馆可供Mocking使用,包括:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM