这真的非常让我感到高兴,所以我希望有人可以给我一个合理的理由来解释为什么事情就像他们一样.
NotImplementedException. 你拉我的腿吧?
不,我不打算通过说,"坚持,方法实现 - 它会抛出NotImplementedException".是的,没错,你必须实现抛出NotImplementedException的方法(不像C++中的纯虚函数调用 - 现在才有意义!).虽然这很可笑,但在我看来还有一个更严重的问题.
我只是想知道,在存在NotImplementedException的情况下,任何人都可以用.Net做任何事情?您是否希望使用try catch块包装每个抽象方法调用以防止可能未实现的方法?如果你遇到这样的例外,你应该怎么做呢?
我认为没有办法测试一个方法是否在没有调用的情况下实际实现.因为调用它可能有副作用,我不能提前完成所有检查,然后运行我的算法.我必须运行我的算法,捕获NotImplementedExceptions以及一些如何将我的应用程序回滚到一些理智的状态.
这很疯狂.狂.疯.所以问题是: 为什么存在NotImplementedException?
作为先发制人的罢工,我不希望任何人回应,"因为设计师需要将其放入自动生成的代码中." 这太可怕了.在您提供实现之前,我宁愿不编译自动生成的代码.例如,自动生成的实现可能是"throw NotImplementedException;" 其中未定义NotImplementedException!
有没有人捕获并处理过NotImplementedException?你有没有在你的代码中留下NotImplementedException?如果是这样,这是代表定时炸弹(即,你不小心将它留在那里),还是设计缺陷(该方法不应该实施,永远不会被调用)?
我也非常怀疑NotSupportedException ...不支持?什么?如果它不受支持,为什么它是你的界面的一部分?微软的任何人都可以拼写不正当的继承吗?但是如果我对这个问题没有太多的滥用,我可能会提出另一个问题.
附加信息:
这是一个有趣的读物.
似乎与Brad Abrams有一个强烈的一致意见,"NotImplementedException是针对尚未实现的功能,但实际上应该(并且将会是).类似于在构建类时可能开始的内容,获取所有方法抛出NotImplementedException,然后用实际代码刷新它们......"
来自Jared Parsons的注释非常弱,应该可以忽略:NotImplementedException:当类型由于任何其他原因没有实现方法时抛出此异常.
在MSDN上的主题更弱,只是说,"当一个请求的方法或操作未实现时引发的异常."
有一种情况我发现它很有用:TDD.
我编写测试,然后创建存根,以便测试编译.那些存根什么都不做throw new NotImplementedException();
.这样,无论如何,默认情况下测试都会失败.如果我使用了一些虚拟返回值,则可能会产生误报.现在所有测试都编译并失败,因为没有实现,我处理这些存根.
因为我从来没有NotImplementedException
在任何其他情况下使用过,所以NotImplementedException
不会传递给发布代码,因为它总会使某些测试失败.
你不需要在整个地方捕获它.好的API记录抛出的异常.那些是你应该寻找的.
编辑:我写了一个FxCop规则来找到它们.
这是代码:
using System; using Microsoft.FxCop.Sdk; ////// An FxCop rule to ensure no internal class DoNotRaiseNotImplementedException : BaseIntrospectionRule { private TypeNode _notImplementedException; private Member _currentMember; public DoNotRaiseNotImplementedException() : base("DoNotRaiseNotImplementedException", // The following string must be the assembly name (here // Bevonn.CodeAnalysis) followed by a dot and then the // metadata file name without the xml extension (here // DesignRules). See the note at the end for more details. "Bevonn.CodeAnalysis.DesignRules", typeof (DoNotRaiseNotImplementedException).Assembly) { } public override void BeforeAnalysis() { base.BeforeAnalysis(); _notImplementedException = FrameworkAssemblies.Mscorlib.GetType( Identifier.For("System"), Identifier.For("NotImplementedException")); } public override ProblemCollection Check(Member member) { var method = member as Method; if (method != null) { _currentMember = member; VisitStatements(method.Body.Statements); } return Problems; } public override void VisitThrow(ThrowNode throwInstruction) { if (throwInstruction.Expression != null && throwInstruction.Expression.Type.IsAssignableTo(_notImplementedException)) { var problem = new Problem( GetResolution(), throwInstruction.SourceContext, _currentMember.Name.Name); Problems.Add(problem); } } }is /// left behind on production code. ///
这是规则元数据:
Do not raise NotImplementedException NotImplementedException should not be used in production code. http://stackoverflow.com/questions/410719/notimplementedexception-are-they-kidding-me Implement the method or property accessor. CriticalError NonBreaking
要构建它,您需要:
参考Microsoft.FxCop.Sdk.dll
和Microsoft.Cci.dll
将元数据放入调用的文件中DesignRules.xml
,并将其作为嵌入式资源添加到程序集中
命名你的程序集Bevonn.CodeAnalysis
.如果要对元数据或汇编文件使用不同的名称,请确保相应地将第二个参数更改为基本构造函数.
然后只需将生成的程序集添加到您的FxCop规则中,并从您的宝贵代码中取出那些该死的异常.有一些极端情况下,当一个人被抛出时它不会报告NotImplementedException但是如果你真的在编写这样的cthulhian代码,我真的认为你没有希望.对于正常使用,即throw new NotImplementedException();
它起作用,这就是最重要的.
它支持一个相当常见的用例,一个有效但只能部分完成的API.说我希望开发人员测试和评估我的API - WashDishes()
至少在我的机器上工作,但我还没有开始编码DryDishes()
,更不用说了PutAwayDishes()
.而不是默默地失败,或给出一些神秘的错误信息,我可以很清楚为什么DryDishes()
不起作用 - 我还没有实现它.
它的姐妹例外NotSupportedException
主要适用于提供者模型.许多洗碗机具有烘干功能,因此属于界面,但我的折扣洗碗机不支持它.我可以让它通过NotSupportedException
我将在一个地方总结我对此的看法,因为它们分散在几条评论中:
您NotImplementedException
用来表示接口成员尚未实现,但将是.您可以将其与自动化单元测试或QA测试结合起来,以确定仍需要实施的功能.
实现该功能后,您将删除该功能NotImplementedException
.为该功能编写了新的单元测试,以确保其正常工作.
NotSupportedException
通常用于不支持对特定类型没有意义的功能的提供程序.在这些情况下,特定类型抛出异常,客户端捕获它们并在适当时处理它们.
框架中存在NotImplementedException
和NotSupportedException
存在的原因很简单:导致它们的情况很常见,因此在框架中定义它们是有意义的,这样开发人员就不必继续重新定义它们.此外,它使客户端更容易知道要捕获的异常(特别是在单元测试的上下文中).如果你必须定义自己的异常,他们必须找出要捕获的异常,这至少是一个适得其反的时间接收器,并且经常是不正确的.
为什么存在NotImplementedException?
NotImplementedException是一个很好的方式来表示某些东西尚未准备好.为什么它没有准备好是方法作者的一个单独的问题.在生产代码中你不太可能捕获这个异常,但如果你这样做,你可以立即看到发生了什么,它比试图弄清楚为什么方法被调用但没有发生甚至更糟 - 获得一些"临时"结果并得到更好"有趣"的副作用.
NotImplementedException是Java的UnsupportedOperationException的C#等价物吗?
不,.NET有NotSupportedException
我必须运行我的算法,捕获NotImplementedExceptions以及一些如何将我的应用程序回滚到一些理智的状态
Good API具有描述可能异常的XML方法文档.
我也非常怀疑NotSupportedException ...不支持?什么?如果它不受支持,为什么它是你的界面的一部分?
可能有数百万个原因.例如,您可以引入新版本的API,并且不希望/不能支持旧方法.再次,看到描述性异常而不是深入研究文档或调试第三方代码要好得多.
NotImplementedException异常的主要用途是生成的存根代码:这样你就不会忘记实现它!例如,Visual Studio将显式实现接口的方法/属性,并且主体抛出NotImplementedException.
重新NotImplementedException
- 这有一些用途; 它提供了一个例外(例如)您的单元测试可以锁定不完整的工作.但是,它确实做了所说的:这根本就不存在(还).例如,对于MS库中存在的方法,"mono"会将其全部抛出,但尚未编写.
重新NotSupportedException
- 不是一切都可用.例如,许多接口都支持一对"你可以这样做吗?"/"做这个".如果"你能做到吗?" 返回false,抛出"do this"是完全合理的NotSupportedException
.例子可能是IBindingList.SupportsSearching
/ IBindingList.Find()
等等
Microsoft的大多数开发人员都熟悉NotImplementedException适合的设计模式.这实际上相当普遍.
一个很好的例子是复合模式,其中许多对象可以被视为对象的单个实例.组件用作(正确)继承的叶类的基本抽象类.例如,File和Directory类可以从相同的抽象基类继承,因为它们是非常相似的类型.这样,它们可以被视为一个单独的对象(当你考虑什么文件和目录时这是有意义的 - 例如在Unix中,一切都是文件).
因此,在此示例中,Directory类将有一个GetFiles()方法,但是,File类不会实现此方法,因为这样做没有意义.相反,您会收到NotImplementedException,因为File没有像Directory那样生成子项.
请注意,这不仅限于.NET - 您将在许多OO语言和平台中遇到此模式.
为什么你觉得需要抓住每一个可能的例外?你也包装每个方法调用catch (NullReferenceException ex)
吗?
存根代码抛出NotImplementedException
是占位符,如果它使它发布它应该是bug就像NullReferenceException
.
我认为MS为框架添加NotImplementedException有很多原因:
为方便起见; 由于许多开发人员在开发过程中需要它,为什么每个人都必须自己动手?
因此工具可以依赖它的存在; 例如,Visual Studio的"实现接口"命令生成抛出NotImplementedException的方法存根.如果它不在框架中,这是不可能的,或者至少相当尴尬(例如,它可以生成在您添加自己的NotImplementedException之前不编译的代码)
鼓励一致的"标准做法"
Frankodwyer认为NotImplementedException是一种潜在的定时炸弹.我会说任何未完成的代码都是一个定时炸弹,但NotImplementedException比替代方案更容易解除武装.例如,您可以让构建服务器扫描此类的所有用途的源代码,并将其报告为警告.如果你想真正禁止它,你甚至可以在源代码控制系统中添加一个预提交钩子,以防止签入此类代码.
当然,如果你滚动自己的NotImplementedException,你可以从最终版本中删除它,以确保没有留下时间炸弹.但是,只有在整个团队中始终如一地使用自己的实现时,这才有效,并且您必须确保在发布之前不要忘记将其删除.此外,您可能会发现无法将其删除; 也许有一些可接受的用途,例如测试未发送给客户的代码.
实际上没有理由捕获 NotImplementedException.当被击中时,它应该杀死你的应用程序,并且这样做非常痛苦.修复它的唯一方法不是捕获它,而是更改源代码(实现被调用的方法或更改调用代码).