.NET中的事件有一个标准模式 - 它们使用一个delegate类型,它接受一个名为sender的普通对象,然后是第二个参数中的实际"payload",它应该从中派生出来EventArgs.
派生的第二个参数的基本原理EventArgs似乎非常清楚(请参阅.NET Framework标准库带注释的参考).它旨在确保随着软件的发展,事件接收器和源之间的二进制兼容性.对于每个事件,即使它只有一个参数,我们派生一个自定义事件参数类,它具有包含该参数的单个属性,这样我们就可以保留在未来版本中向有效负载添加更多属性而不破坏现有客户端代码的能力. .在独立开发组件的生态系统中非常重要.
但我发现零参数也是如此.这意味着如果我的第一个版本中有一个没有参数的事件,我会写:
public event EventHandler Click;
Run Code Online (Sandbox Code Playgroud)
......然后我做错了.如果我将来的委托类型更改为新的类作为其有效负载:
public class ClickEventArgs : EventArgs { ...
Run Code Online (Sandbox Code Playgroud)
...我将破坏与客户的二进制兼容性.客户端上界到内部方法的具体超载add_Click是需要EventHandler的,如果我改变了委托类型,然后他们无法找到超载,所以有一个MissingMethodException.
好的,那么如果我使用方便的通用版本怎么办?
public EventHandler<EventArgs> Click;
Run Code Online (Sandbox Code Playgroud)
不,仍然是错的,因为一个EventHandler<ClickEventArgs>不是EventHandler<EventArgs>.
因此,为了获得好处EventArgs,您必须从中获取,而不是直接使用它.如果你不这样做,你也可以不使用它(在我看来).
然后是第一个论点,sender.在我看来,这似乎是一个邪恶的耦合配方.事件触发本质上是一个函数调用.一般来说,这个函数是否应该能够通过堆栈挖掘并找出调用者是谁,并相应地调整其行为?我们应该强制要求接口看起来像这样吗?
public interface IFoo
{
void Bar(object caller, int actualArg1, ...);
}
Run Code Online (Sandbox Code Playgroud)
毕竟,实现者Bar可能想知道是谁caller,所以他们可以查询更多信息!我希望你现在正在呕吐.为什么事件会有所不同?
因此,即使我已经准备好为EventArgs我声明的每个事件都要为一个独立的派生类而烦恼,只是为了让它值得我在使用EventArgs时,我绝对宁愿删除对象发送者参数.
Visual Studio的自动完成功能似乎并不关心您用于事件的委托 - 您可以键入+= [命中空间,返回]并为您编写一个匹配任何委托的处理程序方法.
那么偏离标准模式我会失去什么价值? …
我找到了这个工具,http://sab39.netreach.com/Software/Japitools/JDK-Results/46/,它使用javadoc检查不同版本的Java之间的向后兼容性.
是否有一个与C#/ .NET相当的工具?
以下是使用此工具对JDK 1.5和JDK 6 API进行比较的示例:http: //www.kaffe.org/~stuart/japi/htmlout/h-jdk15-jdk6
我想验证2个JAR之间的二进制兼容性.
根据这个答案中的建议,我使用jboss tattletale,但它只能找到缺少的类.
如何找到缺少的方法?有可能吗?
例如
"取决于 - " Foo 课程取决于Bar(像许多其他中产阶级工人一样)
import org.overlyusedclassnames.Bar
public class Foo{
public void someMethod(){
Bar tender = new Bar();
tender.getJohnnyRedLabel();
tender.getJohnnyBlueLabel(); //this method is new in the Bar class
}
}
Run Code Online (Sandbox Code Playgroud)
"编译时间"课程
package org.overlyusedclassnames;
/**
* @Since 1992
* Changes: added blue and gold Johnny Walker labels
*/
public class Bar {
public Drink getJohnnyRedLabel(){
return new JohnyWalkerFactory.get(RedLabel.class);
}
public Drink getJohnnyBlackLabel(){
return new JohnyWalkerFactory.get(BlackLabel.class);
}
public Drink getJohnnyGoldLabel(){
return new …Run Code Online (Sandbox Code Playgroud) 希望这个问题不会太模糊.通过COM规范和Don Box的Essential COM书阅读,有很多关于"COM解决的问题"的讨论 - 而且它们听起来都很重要,相关且最新.
那么COM地址在其他系统(linux,unix,OSX,android)上处理的问题怎么样呢?我想的是:
我基本上只是想了解为什么例如Linux上的CORBA不是像COM这样的东西在Windows上(如果这是有道理的).Linux上的软件开发是否可以订阅与COM提出的基于组件的模型不同的理念?
最后,COM是C/C++的东西吗?有几次我遇到过人们的评论,他们说COM被.NET淘汰了,但没有真正解释他们的意思.
"API设计就像性:做出一个错误并在你的余生中支持它" (Josh Bloch在Twitter上)
Java库中存在许多设计错误.Stack extends Vector(讨论),我们无法在不造成破损的情况下解决这个问题.我们可以尝试弃用Integer.getInteger(讨论),但它可能会永远存在.
尽管如此,某些类型的改装可以在不造成破损的情况下完成.
有效的Java第2版,第18项:首选接口到抽象类:现有的类可以很容易地进行改进,以实现新的接口".
例如:String implements CharSequence,Vector implements List,等.
有效的Java第2版,第42项:明智地使用varargs:您可以改进现有方法,该方法将数组作为其最终参数,而不是对现有客户端采取varags.
一个着名的例子是Arrays.asList引起混淆(讨论),但没有破坏.
这个问题是关于不同类型的改造:
void不破坏现有代码的情况下改进返回方法的方法?我最初的预感指向是,因为:
void退货换货是合法的(但不是相反!)Class.getMethod也不会在返回类型上区分但是,我希望听到其他在Java/API设计方面经验丰富的人进行更全面的分析.
正如标题中所建议的那样,一个动机是促进流畅的界面风格编程.
考虑这个简单的代码片段,它打印一个混洗的名称列表:
List<String> names = Arrays.asList("Eenie", "Meenie", "Miny", "Moe");
Collections.shuffle(names);
System.out.println(names);
// prints e.g. [Miny, Moe, Meenie, Eenie]
Run Code Online (Sandbox Code Playgroud)
已经Collections.shuffle(List)被宣布为返回输入列表中,我们可以这样写:
System.out.println(
Collections.shuffle(Arrays.asList("Eenie", …Run Code Online (Sandbox Code Playgroud) 简单的问题:如果改变这个:
void someMethod();
Run Code Online (Sandbox Code Playgroud)
至
void someMethod() noexcept;
Run Code Online (Sandbox Code Playgroud)
它会破坏二进制兼容性,还是方法签名保持不变?
令我惊讶的是,Apache Commons Collections项目仍然没有让他们的图书馆通用识别.我非常喜欢这个库提供的功能,但缺乏对泛型的支持是一个很大的转变.Commons Collections的Lavalabs分支支持泛型,它似乎声称向后兼容,但当我尝试更新到这个版本时,我的Web应用程序无法启动(在JBoss中).
我的问题是:
顺便说一句,我知道谷歌的收藏品,但在API稳定之前我不愿意使用它.
干杯,唐
java collections upgrade apache-commons binary-compatibility
通过比较代码,可以在编译之前完成吗?有没有工具呢?
c++ automated-tests static-analysis backwards-compatibility binary-compatibility
我有两个场景.假设我有3个导出C++符号的共享库,每个库都使用VS7.1,VS8和VS9构建.我在VS9中编译了所有3个.出于某种原因,这是有效的.我不需要在VS9中为VS9链接器重新编译前两个库,以成功找到符号并链接它们.
现在,如果我有一个只使用C语法(extern"C")导出符号的库,这是一样的吗?我听说有人说ABI for C是标准化的,所以在某种程度上保证你可以在所有版本的Visual Studio中使用Visual Studio 8中编译的C库.
基本上,所有这些事情的结合令人困惑.我不确定在不同版本的Visual Studio之间链接C++和基于C的共享库(使用相应的导入库)之间有什么保证.我想听听关于任何其他版本的Visual Studio上C 和 C++导入或静态库的向前/向后兼容性的一致意见.
这对我来说是因为我使用的闭源库是在Visual Studio .NET 2003(VS7.1)中编译的.我的团队认为这将我们锁定到VS 7.1编译器,但是我已经在VS8和VS9中测试了这些库,甚至是VS2010,它们链接得很好.但是,我不确定这个内在的危险.请注意,所讨论的库具有C变体和C++变体.基本上,C变量是标准C导出,C++库是C库和导出类的抽象.
想象一下DLL中的这个枚举.
public enum Colors
{
Red,
Green
}
Run Code Online (Sandbox Code Playgroud)
添加枚举值是否会破坏二进制兼容性?如果我要更改它,现有的EXE会破坏吗?
public enum Colors
{
Red,
Green,
Blue
}
Run Code Online (Sandbox Code Playgroud)
我看到了这个答案,但它似乎解决了插入值的问题.如果我只在最后添加值,那可以吗?