尝试了解组件中的方法签名更改 [英] Trying to understand method signature changes spanning assemblies

查看:179
本文介绍了尝试了解组件中的方法签名更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们遇到了一个奇怪的问题,促销活动,我希望能用代码解释。我想了解为什么它的行为方式是。

We ran into a strange problem with a promotion and I'm hoping I'll be able to explain it with code. I want to understand why it behaves in the manner it is.

装配1

public static class Foo
{
    public static string DoStuff()
    {
        // Do something

        return "some string";
    }
}

装配2:

public class Bar
{
    public void SomeMethod()
    {
        // I realize the below is not what should be done for catching exceptions, as the exception is never thrown due to the return, and seems unnecessary either way... 
        // this is inherited code and has not been modified to correct.

        try
        {
            var someValue = Foo.DoStuff();
        }
        catch (Exception)
        {
            return;
            throw;
        }
    }
}

要求已更改,以便DoStuff需要拿一个参数,其值会稍微改变一下。请注意,只有装配1.Foo正在更改。

Requirements changed so that DoStuff would need to take in a parameter, the value of which would change the behavior slightly. Note that only assembly 1.Foo is changing.

新Foo

public static class Foo
{
    public static string DoStuff(bool someBool = false)
    {
        // Do something

        return "some string";
    }
}

这个重新编译好了,程序集2能够成功利用改变的方法签名而不投诉。我的签入被执行,并且已经提交了改变的项目dll(注意这只是Assembly 1 dll)。

This recompiled fine, and Assembly 2 was able to successfully utilize the changed method signature without complaint. My check in was performed, and project dlls that had changes were promoted (note this was only Assembly 1 dll).

在升级后,我们发现大会2失败Foo.DoStuff()调用 - 不幸的是,我不能提供一个例外,因为上面的代码吞没了它。

After promotion we found out that Assembly 2 was failing on the Foo.DoStuff() call - unfortunately I cannot provide an exception as the above code was swallowing it.

即使在程序集2中没有实际的代码更改,即使方法签名(至少在我心目中)是相同的,因为为新参数提供了一个默认值。

Even though no actual code changed in Assembly 2, it did seem to have an impact on the dll on recompile, even though the method signature - at least in my mind - is the same due to providing a default value for the new parameter.

我使用dotnet来窥视旧的dll和新的dll(即使没有代码更改为该程序集,并且注意到在旧的DLL中的两个DLL中的默认值参数没有提供,但在重新编译中,提供了默认值参数。

I used dotnet peek in order to peek at the "old dll" and the "new dlls" (even though no code change to that assembly and did note a difference in the two DLLs in that in the old DLL, the default value parameter was not supplied, but in the recompiled, the default value parameter was supplied.

我猜我的问题归结为:


  1. 为什么组装2上的编译代码基于o改变(至少我认为)应该是透明的方法签名?

  2. 避免这种情况的方法只是部署一切?而不是根据代码更改部署?请注意,DLL没有签入,所以没有实际的代码更改到程序集2,虽然DLL是不同的,根据对Assembly 1的更改。


推荐答案


为什么程序集2上的编译代码基于一个方法签名(至少我认为)应该是透明的? / p>

Why does the compiled code on assembly 2 change based on a method signature that (at least I think) should be transparent?

不,不应该。当您不指定与可选参数对应的参数时,默认值将在调用位置提供 - 即您的案例中的程序集2。这就是C#中可选参数的工作原理。这是一个痛苦,但这就是生活。

No, it shouldn't. When you don't specify an argument to correspond with an optional parameter, the default value is provided at the call site - i.e. assembly 2 in your case. That's how optional parameters work in C#. It's a pain, but that's life.


避免这种情况的方法只是部署所有东西?

Would the method of avoiding a situation like this just be "deploy everything"?

是的。基本上,程序集2的源代码意义已经改变,即使代码本身没有 - 所以编译的代码已经改变了,需要重新部署。

Yes. Basically, the meaning of the source in assembly 2 has changed even though the code itself hasn't - so the compiled code has changed, and it needs to be redeployed.

在其他情况下,您可以看到类似这样的细微变化 - 同一旧的客户端代码对新的接收代码进行编译,但具有不同的含义。两个例子:

You can see subtle breaking changes like this in other cases, too - where the same old "client" code compiles against new "receiving" code, but has a different meaning. Two examples:


  • 假设您从 Foo(long x) to Foo(int x)但在呼叫站点,您只将其称为 Foo(5) ...在这两种情况下进行编译,但编译成不同的代码。

  • Suppose you change a method signature from Foo(long x) to Foo(int x) but at the call site, you only call it as Foo(5)... that compiles in both cases, but to different code.

假设您已经从 Foo(int x ,int y) to Foo(int y,int x),你有一个呼叫 Foo(x:5 ,y:2) ...再次,代码的含义 Foo(5,2) Foo(2,5),如果你看到我的意思。对新的接收代码重新编译不变的源代码将会改变行为。

Suppose you have change a method signature from Foo(int x, int y) to Foo(int y, int x) and you have a call of Foo(x: 5, y: 2)... again, the meaning of the code changes from Foo(5, 2) to Foo(2, 5), if you see what I mean. Recompiling the unchanged source code against the new "receiving" code will change the behaviour.

假设你在程序集1中有常量,例如 public const string Foo =Foo; 。如果将其更改为 public const string Foo =Bar,但不要使用常量重新编译程序集,那么这些程序集仍然会使用值Foo。 (这也适用于可选参数的默认值。)

Suppose you have a constant in assembly 1, e.g. public const string Foo = "Foo";. If you change that to public const string Foo = "Bar", but don't recompile assemblies using the constant, those assemblies will still use a value of "Foo". (This goes for default values of optional parameters, too.)

这篇关于尝试了解组件中的方法签名更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆