.net 为什么 NotImplementedException 存在?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/410719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:55:35  来源:igfitidea点击:

Why does NotImplementedException exist?

.netexceptionexception-handlingnotimplementedexceptionnotsupportedexception

提问by Daniel Paull

This really, really urks me, so I hope that someone can give me a reasonable justification for why things are as they are.

这真的,真的让我感到不安,所以我希望有人能给我一个合理的理由来解释为什么事情是这样。

NotImplementedException.You are pulling my leg, right?

未实现异常。你在拉我的腿,对吧?

No, I'm not going to take the cheap stab at this by saying, "hang on, the method is implemented - it throws a NotImplementedException." Yes, that's right, you have to implement the method to throw a NotImplementedException (unlike a pure virtual function call in C++ - now that makes sense!). While that's pretty damn funny, there is a more serious problem in my mind.

不,我不会通过说“等一下,该方法已实现 - 它抛出 NotImplementedException”来对此进行廉价攻击。是的,没错,您必须实现抛出 NotImplementedException 的方法(与 C++ 中的纯虚函数调用不同 - 现在说得通了!)。虽然这很可笑,但在我的脑海中还有一个更严重的问题。

I just wonder, in the presence of the NotImplementedException, how can anyone do anything with .Net? Are you expected to wrap every abstract method call with a try catch block to guard against methods that might not be implemented? If you catch such an exception, what the heck are you supposed to do with it??

我只是想知道,在 NotImplementedException 的存在下,任何人怎么能用 .Net 做任何事情?您是否希望用 try catch 块包装每个抽象方法调用以防止可能未实现的方法?如果你捕捉到这样的异常,你到底该怎么处理它??

I see no way to test if a method is actually implemented without calling it. Since calling it may have side effects, I can't do all my checks up-front and then run my algorithm. I have to run my algorithm, catch NotImplementedExceptions and the some how roll back my application to some sane state.

我认为没有办法测试一个方法是否在不调用它的情况下实际实现。由于调用它可能会产生副作用,因此我无法预先进行所有检查,然后再运行我的算法。我必须运行我的算法,捕获 NotImplementedExceptions 以及一些如何将我的应用程序回滚到某种正常状态的方法。

It's crazy. Mad. Insane. So the question is: Why does the NotImplementedException exist?

这很疯狂。疯狂的。疯狂的。所以问题是: 为什么 NotImplementedException 存在

As a preemptive strike, I do not want anyone to respond with, "because designers need to put this in the auto-generated code." This is horrid. I would rather the auto-generated code not compile until you supply an implementation. For example, the auto generated implementation could be "throw NotImplementedException;" where the NotImplementedException is not defined!

作为先发制人的打击,我不希望任何人回应,“因为设计师需要将其放入自动生成的代码中。” 这太可怕了。在您提供实现之前,我宁愿不编译自动生成的代码。例如,自动生成的实现可以是“throw NotImplementedException;” 其中 NotImplementedException 未定义!

Has anyone ever caught and handled a NotImplementedException? Have you ever left a NotImplementedException in your code? If so, did this represent a time bomb (ie, you accidentally left it there), or a design flaw (the method should not be implemented and will never be called)?

有没有人曾经捕获并处理过 NotImplementedException?你有没有在你的代码中留下 NotImplementedException ?如果是这样,这是否代表一个定时炸弹(即,您不小心将其留在那里),或设计缺陷(该方法不应该被实现并且永远不会被调用)?

I'm very suspicious of the NotSupportedException also... Not supported? What the? If it's not supported, why is it part of your interface? Can anyone at Microsoft spell improper inheritance? But I might start another question for that if I don't get too abuse for this one.

我也非常怀疑 NotSupportedException ......不支持?什么?如果它不受支持,为什么它是您界面的一部分?Microsoft 的任何人都可以拼写不正确的继承吗?但是,如果我不会因为这个问题受到太多虐待,我可能会为此提出另一个问题。

Additional info:

附加信息:

Thisis an interesting read on the subject.

是一篇关于这个主题的有趣读物。

There seems to be a strong agreement with Brad Abramsthat "NotImplementedException is for functionality that is just not yet implemented, but really should (and will be). Something like what you might startwith when you are building a class, get all the methods there throwing NotImplementedException, then flush them out with real code…"

似乎与Brad Abrams达成了强烈的共识,“NotImplementedException 用于尚未实现但确实应该(并且将会实现)的功能。就像您在构建类时可能开始的那样,获取所有方法那里抛出 NotImplementedException,然后用真正的代码将它们清除……”

Comments from Jared Parsonsare very weak and should probably be ignored: NotImplementedException: Throw this exception when a type does not implement a method for any other reason.

来自Jared Parsons 的评论非常薄弱,可能应该被忽略: NotImplementedException:当一个类型由于任何其他原因没有实现方法时抛出此异常。

The MSDNis even weaker on the subject, merely stating that, "The exception that is thrown when a requested method or operation is not implemented."

MSDN上的主题更弱,只是说,“当一个请求的方法或操作未实现时引发的异常。”

回答by R. Martinho Fernandes

There is one situation I find it useful: TDD.

我觉得有一种情况很有用:TDD。

I write my tests, then I create stubs so the tests compile. Those stubs do nothing but throw new NotImplementedException();. This way the tests will fail by default, no matter what. If I used some dummy return value, it might generate false positives. Now that all tests compile and fail because there is no implementation, I tackle those stubs.

我编写我的测试,然后我创建存根以便测试编译。这些存根除了throw new NotImplementedException();. 这样,无论如何,默认情况下测试都会失败。如果我使用了一些虚拟返回值,它可能会产生误报。现在所有测试都编译并失败,因为没有实现,我处理这些存根。

Since I never use a NotImplementedExceptionin any other situation, no NotImplementedExceptionwill ever pass onto release code, since it will always make some test fail.

因为我从来没有NotImplementedException在任何其他情况下使用过,所以NotImplementedException不会传递给发布代码,因为它总是会使某些测试失败。

You don't need to catch it all over the place. Good APIs document the exceptions thrown. Those are the ones you should look for.

你不需要到处抓住它。好的 API 会记录抛出的异常。这些是你应该寻找的。

EDIT: I wrote an FxCop rule to find them.

编辑:我写了一个 FxCop 规则来找到它们。

This is the code:

这是代码:

using System;
using Microsoft.FxCop.Sdk;

/// <summary>
/// An FxCop rule to ensure no <see cref="NotImplementedException"/> is
/// left behind on production code.
/// </summary>
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);
        }
    }
}

And this is the rule metadata:

这是规则元数据:

<?xml version="1.0" encoding="utf-8" ?>
<Rules FriendlyName="Bevonn Design Rules">
  <Rule TypeName="DoNotRaiseNotImplementedException" Category="Bevonn.Design" CheckId="BCA0001">
    <Name>Do not raise NotImplementedException</Name>
    <Description>NotImplementedException should not be used in production code.</Description>
    <Url>http://stackoverflow.com/questions/410719/notimplementedexception-are-they-kidding-me</Url>
    <Resolution>Implement the method or property accessor.</Resolution>
    <MessageLevel Certainty="100">CriticalError</MessageLevel>
    <Email></Email>
    <FixCategories>NonBreaking</FixCategories>
    <Owner></Owner>
  </Rule>
</Rules>

To build this you need to:

要构建它,您需要:

  • reference Microsoft.FxCop.Sdk.dlland Microsoft.Cci.dll

  • Put the metadata in a file called DesignRules.xmland add it as an embedded resource to your assembly

  • Name your assembly Bevonn.CodeAnalysis. If you want to use different names for either the metadata or the assembly files, make sure you change the second parameter to the base constructor accordingly.

  • 参考Microsoft.FxCop.Sdk.dllMicrosoft.Cci.dll

  • 将元数据放在一个名为的文件中DesignRules.xml,并将其作为嵌入资源添加到您的程序集中

  • 命名您的程序集Bevonn.CodeAnalysis。如果要为元数据或程序集文件使用不同的名称,请确保相应地将第二个参数更改为基本构造函数。

Then simply add the resulting assembly to your FxCop rules and take those damned exceptions out of your precious code. There are some corner cases where it won't report a NotImplementedException when one is thrown but I really think you are hopeless if you're actually writing such cthulhian code. For normal uses, i.e. throw new NotImplementedException();, it works, and that is all that matters.

然后只需将生成的程序集添加到您的 FxCop 规则中,并从您宝贵的代码中删除那些该死的异常。在某些极端情况下,当抛出一个 NotImplementedException 时它不会报告 NotImplementedException 但我真的认为如果你真的在写这样的克苏尔代码,你是绝望的。对于正常使用,即throw new NotImplementedException();,它可以工作,这才是最重要的。

回答by Scott Weinstein

It's there to support a fairly common use case, a working but only partially completed API. Say I want to developers to test and evaluate my API - WashDishes()works, at least on my machine, but I haven't gotten around yet to coding up DryDishes(), let alone PutAwayDishes(). Rather than silently failing, or giving some cryptic error message, I can be quite clear about why DryDishes()doesn't work - I haven't implemented it yet.

它在那里支持一个相当常见的用例,一个工作但只是部分完成的 API。假设我想让开发人员测试和评估我的 API -WashDishes()至少在我的机器上有效,但我还没有开始编码DryDishes(),更不用说PutAwayDishes()。与其默默地失败,或者给出一些神秘的错误消息,我可以很清楚为什么DryDishes()不起作用 - 我还没有实现它。

Its sister exception NotSupportedExceptionmake sense mostly for provider models. Many dishwashers have a drying function, so belongs in the interface, but my discount dishwasher doesn't support it. I can let that be known via the NotSupportedException

它的姊妹例外NotSupportedException主要适用于提供者模型。很多洗碗机都有烘干功能,所以属于接口,但是我的打折洗碗机不支持。我可以通过NotSupportedException

回答by Mike Hofer

I'll summarize my views on this in one place, since they're scattered throughout a few comments:

我将在一个地方总结我对此的看法,因为它们分散在一些评论中:

  1. You use NotImplementedExceptionto indicate that an interface member isn't yet implemented, but will be. You combine this with automated unit testing or QA testing to identify features which still need to be implemented.

  2. Once the feature is implemented, you remove the NotImplementedException. New unit tests are written for the feature to ensure that it works properly.

  3. NotSupportedExceptionis generally used for providers that don't support features that don't make sense for specific types. In those cases, the specific types throw the exception, the clients catch them and handle them as appropriate.

  4. The reason that both NotImplementedExceptionand NotSupportedExceptionexist in the Framework is simple: the situations that lead to them are common, so it makes sense to define them in the Framework, so that developers don't have to keep redefining them. Also, it makes it easy for clients to know which exception to catch (especially in the context of a unit test). If you have to define your own exception, they have to figure out which exception to catch, which is at the very least a counter-productive time sink, and frequently incorrect.

  1. NotImplementedException用来指示接口成员尚未实现,但将实现。您将其与自动化单元测试或 QA 测试相结合,以确定仍需要实现的功能。

  2. 实现该功能后,您将删除NotImplementedException. 为该功能编写了新的单元测试,以确保其正常工作。

  3. NotSupportedException通常用于不支持对特定类型没有意义的功能的提供者。在这些情况下,特定类型抛出异常,客户端捕获它们并适当地处理它们。

  4. NotImplementedExceptionNotSupportedException存在于Framework 中的原因很简单:导致它们的情况很常见,所以在Framework 中定义它们是有意义的,这样开发人员就不必不断重新定义它们。此外,它使客户很容易知道要捕获哪个异常(尤其是在单元测试的上下文中)。如果您必须定义自己的异常,他们必须弄清楚要捕获哪个异常,这至少会适得其反,而且经常是不正确的。

回答by aku

Why does the NotImplementedException exist?

为什么存在 NotImplementedException?

NotImplementedException is a great way to say that something is not ready yet. Why it's not ready is a separate question for method's authors. In production code you're unlikely to catch this exception, but if you did you can immediately see what happened and it's much better than trying to figure out why methods was called but nothing happened or even worse - receive some "temporary" result and get "funny" side effects.

NotImplementedException 是一个很好的方式来表示某些东西还没有准备好。为什么它没有准备好是方法作者的一个单独问题。在生产代码中,你不太可能捕捉到这个异常,但是如果你捕捉到了这个异常,你可以立即看到发生了什么,这比试图找出方法被调用但什么也没发生或更糟的原因要好得多 - 接收一些“临时”结果并得到“有趣”的副作用。

Is NotImplementedException the C# equivalent of Java's UnsupportedOperationException?

NotImplementedException 是 Java 的 UnsupportedOperationException 的 C# 等价物吗?

No, .NET has NotSupportedException

不,.NET 有 NotSupportedException

I have to run my algorithm, catch NotImplementedExceptions and the some how roll back my application to some sane state

我必须运行我的算法,捕获 NotImplementedExceptions 以及一些如何将我的应用程序回滚到某种正常状态的方法

Good API has XML methods documentation that describes possible exceptions.

好的 API 具有描述可能异常的 XML 方法文档。

I'm very suspicious of the NotSupportedException also... Not supported? What the? If it's not supported, why is it part of your interface?

我也非常怀疑 NotSupportedException ......不支持?什么?如果它不受支持,为什么它是您界面的一部分?

There can be millions reasons. For example you can introduce new version of API and don't want to/can't support old methods. Again, it is much better to see descriptive exception rather then digging into documentation or debugging 3rd party code.

可能有数百万个原因。例如,您可以引入新版本的 API 而不想/不能支持旧方法。同样,最好查看描述性异常,而不是深入研究文档或调试 3rd 方代码。

回答by Mitch Wheat

The main use for a NotImplementedException exception is in generated stub code: that way you don't forget to implement it!! For example, Visual Studio will explicitly implement an interface's methods/properties with the body throwing a NotImplementedException.

NotImplementedException 异常的主要用途是在生成的存根代码中:这样你就不会忘记实现它!!例如,Visual Studio 将通过抛出 NotImplementedException 的主体显式实现接口的方法/属性。

回答by Marc Gravell

Re NotImplementedException- this serves a few uses; it provides a single exception that (for example) your unit tests can lock onto for incomplete work. But also, it really does do what is says: this simply isn't there (yet). For example, "mono" throws this all over the place for methods that exist in the MS libs, but haven't been written yet.

Re NotImplementedException- 这有一些用途;它提供了一个异常(例如)您的单元测试可以锁定未完成的工作。而且,它确实做到了它所说的:这根本不存在(还)。例如,对于 MS 库中存在但尚未编写的方法,“mono”会到处抛出它。

Re NotSupportedException- not everything is available. For example, many interfaces support a pair "can you do this?" / "do this". If the "can you do this?" returns false, it is perfectly reasonable for the "do this" to throw NotSupportedException. Examples might be IBindingList.SupportsSearching/ IBindingList.Find()etc.

重新NotSupportedException- 并非一切都可用。例如,很多接口都支持一对“你能做到这一点吗?” / “做这个”。如果“你能做到吗?” 返回 false,“do this”抛出是完全合理的NotSupportedException。示例可能是IBindingList.SupportsSearching/IBindingList.Find()等。

回答by Marc Gravell

Most developers at Microsoft are familiar with design patterns in which a NotImplementedException is appropriate. It's fairly common actually.

Microsoft 的大多数开发人员都熟悉适合 NotImplementedException 的设计模式。其实挺常见的。

A good example is a Composite Pattern, where many objects can be treated as a single instance of an object. A component is used as a base abstract class for (properly) inherited leaf classes. For example, a File and Directory class may inherit from the same abstract base class, because they are very similar types. This way, they can be treated as a single object (which makes sense when you think about what files and directories are - in Unix for example, everything is a file).

一个很好的例子是复合模式,其中许多对象可以被视为一个对象的单个实例。组件用作(正确)继承的叶类的基本抽象类。例如,文件和目录类可能继承自同一个抽象基类,因为它们是非常相似的类型。这样,它们可以被视为单个对象(当您考虑文件和目录是什么时,这很有意义 - 例如在 Unix 中,一切都是文件)。

So in this example, there would be a GetFiles() method for the Directory class, however, the File class would not implement this method, because it doesn't make sense to do so. Instead, you get a NotImplementedException , because a File does not have children the way a Directory does.

所以在这个例子中,Directory 类会有一个 GetFiles() 方法,但是 File 类不会实现这个方法,因为这样做没有意义。相反,您会得到 NotImplementedException ,因为 File 不像 Directory 那样有子级。

Note that this is not limited to .NET - you'll come across this pattern in many OO languages and platforms.

请注意,这不仅限于 .NET - 您会在许多 OO 语言和平台中遇到这种模式。

回答by orip

Why do you feel the need to catch every possible exception? Do you wrap every method call with catch (NullReferenceException ex)too?

为什么你觉得有必要捕捉每一个可能的异常?你是否也包装了每个方法调用catch (NullReferenceException ex)

Stub code throwing NotImplementedExceptionis a placeholder, if it makes it to release it should be bug just like NullReferenceException.

存根代码抛出NotImplementedException是一个占位符,如果它让它释放它应该是错误,就像NullReferenceException.

回答by oefe

I think there are many reasons why MS added NotImplementedException to the framework:

我认为 MS 在框架中添加 NotImplementedException 的原因有很多:

  • As a convenience; since many developers will need it during development, why should everybody have to roll their own?
  • So that tools can rely on its presence; for example, Visual Studio's "Implement Interface" command generate method stubs that throw NotImplementedException. If it were not in the framework, this would not be possible, or at least rather awkward (for example, it could generate code that doesn't compile until you add your own NotImplementedException)
  • To encourage a consistent "standard practice"
  • 为方便起见;既然很多开发者在开发过程中都会用到它,那为什么每个人都要自己roll呢?
  • 这样工具就可以依赖它的存在;例如,Visual Studio 的“实现接口”命令生成抛出 NotImplementedException 的方法存根。如果它不在框架中,这将是不可能的,或者至少相当笨拙(例如,它可能会生成在您添加自己的 NotImplementedException 之前无法编译的代码)
  • 鼓励一致的“标准做法”

Frankodwyer thinks of NotImplementedException as a potential timebomb. I would say that any unfinished code is a timebomb, but NotImplementedException is much easier to disarm than the alternatives. For example, you could have your build server scan the source code for all uses of this class, and report them as warnings. If you want to be really ban it, you could even add a pre-commit hook to your source-control system that prevents checkin of such code.

Frankodwyer 认为 NotImplementedException 是一个潜在的定时炸弹。我会说任何未完成的代码都是定时炸弹,但 NotImplementedException 比替代方案更容易解除。例如,您可以让构建服务器扫描该类的所有用途的源代码,并将它们报告为警告。如果您想真正禁止它,您甚至可以在源代码控制系统中添加一个预提交钩子,以防止签入此类代码。

Sure, if you roll your own NotImplementedException, you can remove it from the final build to make sure that no time bombs are left. But this will only work if you use your own implementation consistently in the entire team, and you must make sure that you don't forget to remove it before you release. Also, you might find that you can't remove it; maybe there are a few acceptable uses, for example in testing code that is not shipped to customers.

当然,如果您推出自己的 NotImplementedException,您可以将其从最终构建中删除,以确保不会留下定时炸弹。但这只有在您在整个团队中始终如一地使用自己的实现时才有效,并且您必须确保在发布之前不要忘记将其删除。此外,您可能会发现无法删除它;也许有一些可接受的用途,例如在测试未交付给客户的代码中。

回答by jeroenh

There is really no reason to actually catcha NotImplementedException. When hit, it should kill your app, and do so very painfully. The only way to fix it is not by catching it, but changing your source code (either implementing the called method, or changing the calling code).

真的没有理由实际捕获NotImplementedException。当命中时,它应该会杀死您的应用程序,并且这样做非常痛苦。修复它的唯一方法不是捕获它,而是更改源代码(实现被调用的方法或更改调用代码)。