尝试了解组件中的方法签名更改 [英] Trying to understand method signature changes spanning assemblies
问题描述
我们遇到了一个奇怪的问题,促销活动,我希望能用代码解释。我想了解为什么它的行为方式是。
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.
我猜我的问题归结为:
- 为什么组装2上的编译代码基于o改变(至少我认为)应该是透明的方法签名?
- 避免这种情况的方法只是部署一切?而不是根据代码更改部署?请注意,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)
toFoo(int x)
但在呼叫站点,您只将其称为Foo(5)
...在这两种情况下进行编译,但编译成不同的代码。
Suppose you change a method signature from
Foo(long x)
toFoo(int x)
but at the call site, you only call it asFoo(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屋!