SUMTEC -- There's a thing in my bloglet.

But it's not only one. It's many. It's the same as other things but it exactly likes nothing else...

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  263 随笔 :: 19 文章 :: 2993 评论 :: 22 引用

声明:切勿以此为笔试题。

我们很多时候都会激烈的讨论算法、数据结构、设计模式、N层架构、某某框架、系统架构,可是真的在实战当中,才会发现原来有些很简单的问题我们会不知道答案。比如说:

        private static void DoWhileContinueTest()
        {
            
int i = 0;
            
do
            {
                Console.WriteLine(i);
                i
++;
                
if (i < 3continue;
            }
            
while (false);
        }


上面的输出是什么呢?这个问题看起来好像很简单,continue不就是进入下一次循环嘛。可问题是,如何进入呢:是直接走到循环最上面的一行代码呢,还是走到循环条件的判断?for、foreach和while都是走到最上面一行代码,而最上面一行代码都存在或者隐含了循环条件的判断。do-while因为循环判断条件在最后,因此不可能同时符合这两个说法,那么到底哪一个说法才是真的呢?

 

这个问题Google之似乎是找不到答案的,反正我用关键字“do while continue”没有找到,在microsoft.com找也没有找到。MSDN对于continue的描述也只是很简单的说“continue 语句将控制权传递给它所在的封闭迭代语句的下一次迭代”,也没有do-while的continue示例。“一次迭代”这个说法包不包含“循环条件的判断”还真不是显而易见的:do-while的是先执行循环体后判断,如果认为这样算一次迭代,那么下一次迭代也应该认为是先执行循环体,然后再执行判断;如果认为每一次迭代都是先判断循环条件,后执行循环体的,那第一次显然不是这样;又或者可能认为一次迭代不包含循环条件判断,但根据微软的说法又和for、foreach和while等情况不匹配。

 

其实无论结果如何,MSDN上的说法肯定是不严谨的。好吧,我们忽略MSDN的问题,这个疑惑总归要解决的。结果如何,请君自己动手以便加深记忆。

可能有人着急想要知道答案,又或者手头没有开发工具,好吧,我把答案贴出来。
答案是输出:
0

而不是:
0
1
2

也就是说,continue的准确含义是:
立即跳过后面的语句,直达循环条件判断处。
或者说是:立即执行条件判断,如果条件判断成立,则进入下一次迭代,否则跳出循环体。


再比如:

代码
        private static void DynamicTest()
        {
            dynamic t 
= new Host.TestPoint();
            t.Test();
        }

        
public class Host
        {
            
private interface IFace
            {
                
void Test();
            }

            
public class TestPoint : IFace
            {
                
void IFace.Test()
                {
                    Console.WriteLine(
"OK");
                }
            }
        }

 

 

我们知道dynamic是4.0的新特性,是编译器的语法糖。实际上dynamic类型对象在IL里面就是一个object,对其的访问一般来讲就是通过反射来进行调用。(当然,可以通过别的方式来自己扩展,此处忽略。)问题是,这个反射的过程会考虑上面的接口吗?假如不考虑那一定会出错。可是dynamic本身要解决的其中一个问题,是简化ActiveX调用。然而我在实际的使用过程中发现有一个.NET的COM对象上面显式的实现了一个COM接口,也就是说这不是一个Native的COM对象。此时如果不找其中的接口就会导致调用失败,大家猜结果会如何?

可能有人着急想要知道答案,又或者手头没有开发工具,好吧,我把答案贴出来。
答案是抛出了异常,也就是说不考虑其(隐式)实现的接口。

 

有的时候一些简单的问题,也还是挺有趣的。

posted on 2011-02-16 11:30 Sumtec 阅读(1963) 评论(18) 编辑 收藏

评论

#1楼 2011-02-16 12:22 诺贝尔      
第二个用接口去调用或者可以吧?
 回复 引用 查看   

#2楼 2011-02-16 12:38 钧梓昊逑      
最后那个叫 显示实现接口
 回复 引用 查看   

不过第二个抛异常也的确正常。
 回复 引用 查看   

#4楼 2011-02-16 12:59 寻自己      
好久没见楼主犀利的头像
 回复 引用 查看   

#5楼 2011-02-16 13:13 Rainr      
确实没有遇到过这种问题.谢谢LZ分享
 回复 引用 查看   

#6楼 2011-02-16 14:28 Ivony...      
continue 语句的目标是直接封闭它的 while、do、for 或 foreach 语句的嵌入语句的结束点。

——C#规范。
 回复 引用 查看   

#7楼 2011-02-16 14:37 LanceZhang      
很有趣,还没来得及看dynamic呢
 回复 引用 查看   

#8楼 2011-02-16 14:54 小彬      
嘿嘿 猜对了
 回复 引用 查看   

#9楼 2011-02-16 15:04 SnowDreamist      
引用Ivony...:
continue 语句的目标是直接封闭它的 while、do、for 或 foreach 语句的嵌入语句的结束点。

——C#规范。


这么解释就不存在歧义的
 回复 引用 查看   

#10楼 2011-02-16 15:10 SnowDreamist      
博主,为什么第二个例子我测试通过了……
 回复 引用 查看   

#11楼 2011-02-16 15:10 Ivony...      
引用SnowDreamist:博主,为什么第二个例子我测试通过了……


必须是显示接口实现,同时,调用的位置不能位于TestPoint内部,应该是这样。
 回复 引用 查看   

#12楼 2011-02-16 15:14 SnowDreamist      
博主,你的代码的问题出在TestPoint.Test的方式是Private的,dynamic也不能逾越反问修饰限制的,如果你改成public,那么会提示错误,因为你是显示实现的接口。只要改成隐式实现就一切正常。因为显示实现必须通过接口类型调用,而接口类型是private的和public访问修饰冲突。
 回复 引用 查看   

#13楼 2011-02-16 17:07 RealDigit      
@SnowDreamist
是不是哦?
 回复 引用 查看   

#14楼[楼主] 2011-02-17 17:03 Sumtec      
@钧梓昊逑
感谢,已修正笔误。

@SnowDreamist
如Ivony所说……可能你调用的位置和事例中不一样。

此外,我这个例子只是用来演示我遇到的情况,事实上那个类不是我写的,所以我无法修改成能够用dynamic调用的方式,只能够通过自己写反射来实现。
 回复 引用 查看   

#15楼 2011-02-17 17:54 yzx226      
void IFace.Test()

默认是private void ...
 回复 引用 查看   

#16楼 2011-02-18 12:20 Ivony...      
引用Sumtec:
@钧梓昊逑
感谢,已修正笔误。

@SnowDreamist
如Ivony所说……可能你调用的位置和事例中不一样。

此外,我这个例子只是用来演示我遇到的情况,事实上那个类不是我写的,所以我无法修改成能够用dynamic调用的方式,只能够通过自己写反射来实现。



接口的实现有一个很不为人所知的问题,有时候会带来很大的困扰,事实上实现接口的方法名和接口定义的方法名可以是完全不同的。需要通过GetInterfaceMap方法才能获取接口和实现成员的对应关系。
 回复 引用 查看   

#17楼[楼主] 2011-02-20 18:04 Sumtec      
@Ivony...
嗯,VB.NET就是如此,实际上COM的话也是一个相对复杂的过程。这里只是抛砖引玉而已。
 回复 引用 查看   

#18楼 2011-04-29 14:10 take it and go      
猜对了...
 回复 引用 查看