首页 新闻 赞助 找找看

基础题:C#的委托不能定义在函数内部吗?为什么?

1
悬赏园豆:5 [已解决问题] 解决于 2013-12-02 22:36

比如:

Class A {
  //声明在这里是可以的~
  private delegate void test_del(int a);
  
  private void test(){...}

  public void start(){
    //声明在这里就不行了~
    private delegate void test_del(int a);
  }
}

这是为什么呢?如果是相当于函数指针的话应该不会这样吧?

eatpockyboy的主页 eatpockyboy | 菜鸟二级 | 园豆:260
提问于:2013-12-02 12:08
< >
分享
最佳答案
0

楼上都讲到了

委托是一种特殊的类,和普通类不同的是委托是对一类方法的抽象。

因此只能在类内部定义内部类(包括委托、结构和枚举)而不能在方法中定义

 

另外,你所说的类似于函数指针,虽然在C语言中函数指针定义在函数内部不是语法错误的,但是却是一种很不好的编码风格

收获园豆:5
飞鸟_Asuka | 菜鸟二级 |园豆:209 | 2013-12-02 13:10

看了这么多 感觉兄台你是最靠谱的 比那个反问我懂不懂委托的靠谱多了~ 其实对于你说到的结构,枚举这些不能在函数里面定义的类型我也觉得有点奇怪的。。OOP的思想是一切皆对象 那么函数和类还有委托等等这些应该都是对象 这个概念应该是包含与自包含的 如果非要用OOP的来解释 我觉得应该是不能在子类(函数)内定义父类(委托,类,结构等)就是说不能存在反包含,如果这样的话就成了过程化编程了。。过程化的特点就是函数封装。。而你说C的函数指针在函数中定义不是一种好的编码风格这里应该如何理解呢?有例子吗?

eatpockyboy | 园豆:260 (菜鸟二级) | 2013-12-02 14:07

@Gssl: OO当中没有“函数”的概念,这里应该叫做是类的“操作”。就是这一类物体会有的行为。

举个例子,有一个类叫做“汽车”,“启动”是汽车的一个操作,那么怎么可以在“启动”这个操作中再包含一个“汽车”的定义呢?

定义和实现必然是包含在不同的层次的。

至于前面所讲的C语言函数指针不要定义在函数中,其实就和函数或结构体不要定义在函数中一样,因为这就造成了这些类型定义只能专用于一个函数,无法起到复用的目的。

记住,指向函数的指针是一个“类型定义”,类型定义是不能“专用”的。委托也是同样一个道理。

飞鸟_Asuka | 园豆:209 (菜鸟二级) | 2013-12-02 16:04

@Gssl: 另外,除非的确需要定义内部类,否则还是把类(包括委托、结构、枚举)定义在平行的位置。因为一旦定义了内部类,这个类也只能被其外部类“专用”。

飞鸟_Asuka | 园豆:209 (菜鸟二级) | 2013-12-02 16:12

我对C#的结构和枚举也了解了一下 有点明白这么做的用意了。。因为在下一直从事JS的编程 受弱类型语言影响比较深 JS其实就是典型的过程化语言 但是它也能写成OO模式 把函数封装写成类封装这样 因此函数和类的概念会在JS里面融为一体 而重新接触C#之后(大学学的就是C#)发现各种各样的"不合理",或者叫冗余。。对于这些我也只是想寻求一个解释,并无他意。。有些东西就是这样 如果我觉得不合理 那么就无从下手了~ 这或许是强迫症吧~~ 感谢你的回答~ 

eatpockyboy | 园豆:260 (菜鸟二级) | 2013-12-02 22:36

@Gssl: 事实上有个东西叫匿名委托。。。还有lambda表达式,和JS中挺类似的

例如

someObject.SomeMethod(int para1, delegate()
{
     // 委托方法
})

//或者

someObject.SomeMethod(int para1, ()=>{//委托方法})
飞鸟_Asuka | 园豆:209 (菜鸟二级) | 2013-12-02 22:42

@飞鸟_Asuka: 昨晚查了下 其实我是在多线程的时候遇到这个问题 然后拓展开来的。。后来选择了内部类的方式 因为我的线程还需要带一个回参出来 下面的连接是昨晚转的一个link

 http://eatpockyboy.blog.163.com/blog/static/1167346402013112111721445/

目测lambda表达式跟内部类的实现上是差不多的,但是就灵活性上说内部类会比较优秀点吧(主要表现在对于访问或者回调的资源可以封装在类内,通过实例化调用而不是暴露在函数体内或者体外这样。。)。。另外也可以用异步委托来处理。。但是异步委托那个写了出来感觉不靠谱。。。同事说那个比较慢,而且不能用线程池。。现在都删了。。。

eatpockyboy | 园豆:260 (菜鸟二级) | 2013-12-03 11:22
其他回答(6)
0

委托是类型!像class一样是类型!放在class之外,声明就行了!或者单独放一个文件中

可以看张子阳写的关于委托和事件的博客http://www.tracefact.net/Document/Delegates-and-Events-in-CSharp.pdf

秋壶冰月 | 园豆:5903 (大侠五级) | 2013-12-02 12:14
0

委托其实就是一个类,你见过在方法内部声明一个类的吗?

class怎么声明,委托就怎么声明,你记住这个就行了

幕三少 | 园豆:1384 (小虾三级) | 2013-12-02 12:41
0

委托和类 是一个级别的

wolfy | 园豆:2636 (老鸟四级) | 2013-12-02 13:20
0

你搞清楚没? 委托是干什么的!

Albert Fei | 园豆:2102 (老鸟四级) | 2013-12-02 13:41
0

委托是一种特殊的类,委托:是一种数据类型,它类似函数指针,并且是类型安全,可以定义回调方法,只要是与委托的返回类型和参数类型相同的方法(或多个方法)都可以赋值给委托的一个实例,从而提高了程序的扩展性。只能被调用,它里面是不能再写其他类的,http://www.cnblogs.com/QLJ1314/archive/2012/08/11/2633737.html希望这个能给你点帮助,这个是我以前的笔记

妍珊 | 园豆:1169 (小虾三级) | 2013-12-02 14:03
0

作用域的问题,如果允许你这样定义:

public void start(){
    //声明在这里就不行了~
    private delegate void test_del(int a);
  }

那么 test_del 只能在 start() 中使用。

在C++中允许你在函数中定义class ,struct 等等,但是它的作用域只在定义范围内有效。

C#里不允许这么定义,那你就别这么用,这可能只是为了保持代码的可读性。

Launcher | 园豆:45045 (高人七级) | 2013-12-02 17:58
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册