C#:创建抽象类的实例而不定义新类

发布于 2024-07-13 09:28:50 字数 464 浏览 7 评论 0原文

我知道这可以用 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# 中完成吗?如果可以,如何实现?

I know it can be done in Java, as I have used this technique quite extensively in the past. An example in Java would be shown below. (Additional question. What is this technique called? It's hard to find an example of this without a name.)

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();
   }
}

Now, my main question would be, can this also be done in C#, and if so, how?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

带刺的爱情 2024-07-20 09:28:50

Java 技术称为“匿名内部类”, C# 中没有等效的。

The Java technique is called "Anonymous inner class", and there is no equivalent in C#.

一百个冬季 2024-07-20 09:28:50

使用巴巴表达式和类初始值设定项,您可以通过一些努力获得相同的行为。

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 表达式,这将使它们能够访问 example 可能持有的任何公共状态。 AFAIK 在功能上等同于 Java 匿名内部类。

PS 如果您打算对某个答案投反对票,请帮我们大家一个忙,并添加评论说明您不同意的原因:-)

With lamba expressions and class initializers you can get the same behaviour with a bit of effort.

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();
    }
}

One problem with this solution that I just realized is that if you were to create fields in the Example class, the lambda expressions would not be able to access those fields.

However, there is no reason that you could not pass the instance of Example to the lambda expressions which would give them access to any public state that example might hold. AFAIK that would be functionally equivalent to the Java Anonymous Inner Class.

P.S. If you are going to vote an answer down, do us all a favour and add a comment as to why you disagree :-)

沉鱼一梦 2024-07-20 09:28:50

通常,使用 Java 中的匿名内部类解决的问题可以使用 .Net 中的委托以更简洁的方式解决。 你的例子有点太简单了,无法确定你的意图。 如果您使用抽象类的目的是传递“行为”,请考虑仅使用 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();
   }
}

Typically, problems that are solved with anonymous inner classes in Java are solved in a much cleaner fashion using delegates in .Net. Your example is a little too simplistic to determine your intent. If your intent by using the abstract class is to pass around a "behavior" think about just using an Action delegate instead.

public class StartHere{
   public static void main(string[] args){
      Action doStuff = () => Console.WriteLine("Did stuff");
      executeSomething(doStuff);
   }

   public static void executeSomething(Action action)
   {
      action();
   }
}
时光匆匆的小流年 2024-07-20 09:28:50

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

That can't be done in C#; you need to declare a new class type. The closest you can get in C# is probably a named nested class:

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();
   }
}
梦里南柯 2024-07-20 09:28:50

C# 不支持这一点,如果由我决定,也不应该如此。

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

(诚​​然,我们中的很多人已经非常擅长这种单手游戏;现在看来我们至少要等到 java 8 才能关闭......)

This is not supported in C#, and if it were up to me it shouldn't be so either.

The proliferation of inner classes in java is mainly due to the lack of delegates or lambdas, which C# has. So while this type of functionality currently is "your only hope" in java, you can usually use other mechanisms in C# to achieve the same ends. Java feels like playing the piano with one hand in this regard.

(Admittedly a lot of us have gotten quite good at this one-handed playing; and now it seems like we have to wait at least until java 8 for closures...)

梦忆晨望 2024-07-20 09:28:50

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

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

Since your class represents only an action, you can use a delegate in your case, there is an existing delegate :

public delegate void Action();

This is the exact equivalent of your class.

And the déclaration of your anonymous class is even cleaner :

Action action = () => Console.WriteLine("Hello world");
action(); // invoke

you can even use closure :

public void Hello(string name)
{
  Action action = () => Console.WriteLine("Hello " + name);
  action(); // will call the above lambda !
}
油饼 2024-07-20 09:28:50

虽然所有好的答案都建议依赖 C# 3.0,

所以,为了完整起见,我将添加另一种既不使用 lambda 也不使用 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();
    }
}

While all good answers, most of the work arounds suggested rely on C# 3.0

So, for the sake of completeness, I'll add another solution that uses neither lambdas nor Func type (Granted that, as Matt Olenik mentioned in the comments, one could generalize the below delegates to work the same way.). For those, like me who may still be working with C# 2.0. Maybe not the best solution, but it works.

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();
    }
}
飞烟轻若梦 2024-07-20 09:28:50

您可以通过 .NET 中的 Mocking 来完成此任务。 然而,这个功能没有语言支持,我认为它会在 C# 4.0 中提供。 有许多用于模拟的库,包括:

You are able to accomplish this with Mocking in .NET. However there is no in-language support for this feature, I think it will be available in C# 4.0. There are a number of libraries out there for Mocking, including:

箹锭⒈辈孓 2024-07-20 09:28:50

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

编辑: 不,C# 4.0 不会出现,这是我编造的。

In short no, you have to define it as separate sub class. I think this feature is coming C# 4.0 though?

Edit: No it's not coming C# 4.0 I made that up.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文