它已经讨论过堆栈溢出,我们应该更喜欢属性标记接口(接口没有任何成员).MSDN上的接口设计文章也断言了这个建议:
避免使用标记接口(没有成员的接口).
自定义属性提供了标记类型的方法.有关自定义属性的更多信息,请参阅编写自定义属性.如果可以在执行代码之前推迟检查属性,则首选自定义属性.如果您的方案需要编译时检查,则无法遵守此准则.
甚至还有一个FxCop规则来强制执行此建议:
避免空接口
接口定义提供行为或使用合同的成员.无论类型在继承层次结构中出现何种位置,接口描述的功能都可以采用任何类型.类型通过为接口的成员提供实现来实现接口.空接口不定义任何成员,因此,不定义可以实现的合同.
如果您的设计包含期望实现类型的空接口,则可能使用接口作为标记,或者标识一组类型的方法.如果此标识将在运行时发生,则完成此操作的正确方法是使用自定义属性.使用属性的存在或不存在或属性的属性来标识目标类型.如果标识必须在编译时进行,则可以使用空接口.
本文仅说明了您可能忽略警告的一个原因:何时需要对类型进行编译时识别.(这与界面设计文章一致).
如果在编译时使用接口标识一组类型,则可以安全地从此规则中排除警告.
实际问题是:Microsoft在框架类库的设计中(至少在几种情况下)不符合他们自己的建议:IRequiresSessionState接口和IReadOnlySessionState接口.ASP.NET框架使用这些接口来检查它是否应该为特定处理程序启用会话状态.显然,它不用于类型的编译时识别.他们为什么不这样做?我可以想到两个潜在的原因:
微优化:检查对象是否实现接口(obj is IReadOnlySessionState)比使用反射检查属性(type.IsDefined(typeof(SessionStateAttribute), true))更快.大多数时候差异可以忽略不计,但它实际上可能对ASP.NET运行时中的性能关键代码路径很重要.但是,他们可以使用的解决方法就像为每个处理程序类型缓存结果一样.有趣的是,ASMX Web服务(具有类似性能特征)实际上使用EnableSession属性的WebMethod属性来实现此目的.
与使用第三方.NET语言的属性装饰类型相比,可能更有可能支持实现接口.由于ASP.NET被设计为与语言无关,并且ASP.NET 根据指令的属性为类型(可能在CodeDom的帮助下以第三方语言生成)生成代码,因此可能会生成更多感觉使用接口而不是属性.EnableSessionState<%@ Page %>
使用标记接口而不是属性的有说服力的原因是什么?
这只是一个(过早?)优化还是框架设计中的一个小错误?(他们认为反射是"红眼睛的大怪物"吗?)思想?
我有一个具有以下UI形式的应用程序,这些形式来自QMainWindow
我应该登录到LoginWindow中的应用程序,然后将其移至TasksWindow。在TasksWindow中,我将从组合框中选择一个项目,然后移至DetailsWindow并填充与该项目相关的数据。在DetailsWindow上,我将执行菜单操作,以使我返回TasksWindow。
目前,我的想法(以及我尝试过的)是这样的。在main.cpp中:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
LoginWindow loginWindow;
loginWindow.showMaximized();
return app.exec();
}
Run Code Online (Sandbox Code Playgroud)
并在LoginWindow按钮中:
void LoginWindow::on_loginButton_clicked()
{
this->hide(); // hide the login window
TasksWindow tasksWindow;
tasksWindow.showMaximized();
}
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?它变得难以管理,因为现在我必须包括对我应该去的每个窗口类的引用,可能会创建循环引用!
请注意,我正在这样做,并将应用程序编译为Qt Symbian应用程序。
在应用程序窗口之间切换的最佳方法是什么?我曾考虑过使用QStackedWidget,并进行了实际尝试,但是问题是我必须编写所有代码来处理同一文件中的不同事件,并且各个窗口的操作菜单也不同。
救命!:)
是否有免费的Visual Studio插件,可以从记录异常的方法中自动生成try/catch块?
如果光标位于一个很长的函数内的某个地方,有没有办法让Vim告诉用户他/她正在编辑哪个函数?
顺便说一句,我使用taglist,但似乎taglist不会自动更新你的位置,即使你已将光标移动到另一个函数.
我试图使用vs2008查询构建器来创建带参数的查询.我知道在sql server中它可以使用:select col1,col2 from tbl where col3 = @ myParam
它将如何在oracle中输入或者是pl/sql?我在@myParam部分得到了问题.
当我尝试从Visual Studio 2008访问ASP.NET配置页面时,我失败了.我收到一个错误:
"遇到错误.请返回上一页并重试."
这是我点击帮助后得到的消息:"工具已超时.作为安全措施,网站管理工具在一段时间不活动后超时.对machine.config或web.config的更改也可能导致该工具需要重新启动.要继续配置您的网站,请重新启动该工具."
我该怎么解决这个问题?
好的,我不知道为什么Elmah在Windows Azure上部署时没有记录任何错误.另一件事是以前它曾经工作过.环境是一样的.
我检查了我的web.config设置,并在system.webServer下定义了处理程序和模块.它似乎在本地开发(webdev.exe)下记录消息,并且本地sql express模式被导出到sql azure模式(包括存储过程).
唯一的区别是,在主站点上,应用程序在具有多个子域的主域下运行.在本地,这是通过修改主机文件来模拟的.在本地登录,但在部署时不会.
关于我应该怎么做以找出错误的任何想法?最后一个选项是使用诊断程序来跟踪/找出部署时出现的问题,但这是一个皮塔饼.
我需要将CString实例转换为正确分配的实例并将其BSTR传递BSTR给COM方法.要拥有为ANSI和Unicode编译和工作的代码我CString::AllocSysString()用来将任何格式转换CString为Unicode BSTR.
由于没有人拥有返回的BSTR,我需要处理它并在以尽可能最安全的方式完成调用之后以尽可能少的代码完成调用.
目前我ATL::CComBSTR用于终身管理:
ATL::CComBSTR converted;
converted.Attach( sourceString.AllocSysString() ); //simply attaches to BSTR, doesn't reallocate it
interface->CallMethod( converted );
Run Code Online (Sandbox Code Playgroud)
我不喜欢的是我需要两个单独的语句来构造ATL::CComBSTR转换结果的绑定.
有没有更好的方法来完成相同的任务?
我如何使用ExternalInterface将变量传递给javascript函数?
为什么在接口java.util.Collection上定义了iterator()方法,它已经扩展了java.util.Iterable,它定义了这个方法.
我正在考虑某种向后兼容性或在集合级别上对方法编写一些JavaDoc的机会.
还有其他想法吗?