问题标签 [design-rationale]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
7 回答
2940 浏览

c# - 为什么 C#(或 .NET)不允许我们在接口中放置静态/共享方法?

为什么 C#(或 .NET)不允许我们在接口中放置静态/共享方法?

貌似从这里重复。但我的想法有点不同,我只想为我的插件(接口)添加一个助手

C# 至少不应该允许这个想法吗?

0 投票
13 回答
17556 浏览

c++ - 如果键不存在,为什么 std::map operator[] 会创建一个对象?

我很确定我已经在某个地方看到了这个问题(comp.lang.c++?谷歌似乎也没有在那里找到它)但是在这里快速搜索似乎没有找到它,所以它是:

如果键不存在,为什么 std::map operator[] 会创建一个对象?我不知道,但对我来说,如果你与大多数其他 operator[](如 std::vector)相比,这似乎违反直觉,如果你使用它,你必须确保索引存在。我想知道在 std::map 中实现这种行为的理由是什么。就像我说的那样,当使用无效键访问时,更像是向量中的索引和崩溃(我猜是未定义的行为)不是更直观吗?

看到答案后细化我的问题:

好的,到目前为止,我得到了很多答案,说它基本​​上很便宜,所以为什么不或类似的东西。我完全同意这一点,但为什么不为此使用专用函数(我认为其中一条评论说在 java 中没有 operator[] 并且该函数称为 put)?我的观点是为什么 map operator[] 不像矢量那样工作?如果我在向量的超出范围索引上使用 operator[],即使它很便宜,我也不希望它插入一个元素,因为这可能意味着我的代码中有错误。我的观点是为什么它与地图不一样。我的意思是,对我来说,在地图上使用 operator[] 意味着:我知道这个密钥已经存在(无论出于何种原因,我只是插入了它,我在某处有冗余,无论如何)。我认为这样会更直观。

那就是说使用 operator[] 执行当前行为有什么好处(仅为此,我同意应该存在具有当前行为的函数,而不是 operator[])?也许这样可以提供更清晰的代码?我不知道。

另一个答案是它已经以这种方式存在,所以为什么不保留它,但是,可能当他们(stl 之前的那些)选择以这种方式实现它时,他们发现它提供了优势或什么?所以我的问题基本上是:为什么选择以这种方式实现它,这意味着与其他 operator[] 有点缺乏一致性。它有什么好处?

谢谢

0 投票
3 回答
33483 浏览

delphi - Delphi:什么是Application.Handle?

是什么TApplication.Handle

  • 它从何而来?
  • 它为什么存在?
  • 最重要的是:为什么所有表单都将其作为父窗口句柄?

德尔福帮助说:

TApplication.Handle

提供对应用程序主窗体(窗口)的窗口句柄的访问。

描述

在调用需要父窗口句柄的 Windows API 函数时使用句柄。例如,显示其自己的顶级弹出窗口的 DLL 需要一个父窗口来在应用程序中显示其窗口。使用 Handle 属性使此类窗口成为应用程序的一部分,以便它们与应用程序一起最小化、恢复、启用和禁用。

如果我专注于“应用程序主窗体的窗口句柄”一词,并且我认为它是指应用程序主窗体的窗口句柄,那么我可以比较:

  • “应用程序主窗体的窗口句柄”,带有
  • MainForm的窗口句柄Application

但它们不一样:

那么是什么Application.Handle

  • 它从何而来?
  • 它是什么 Windows® 窗口句柄?
  • 如果Application's的 Windows® 窗口句柄MainForm,那么它们为什么不匹配?
  • 如果不是Application's的窗口句柄MainForm,那是什么?
  • 更重要的是:为什么它是每个表单的最终所有者?
  • 最重要的是:如果我尝试让表单成为无父无主的表单(因此它可以出现在任务栏上),或者尝试使用IProgressDialog之类的东西,为什么一切都会变得混乱?

我真正要问的是:使Application.Handle存在的设计原理是什么?如果我能理解为什么,那么应该如何变得显而易见。


通过二十个问题的游戏更新理解:

在谈到通过设置其所有者使窗口出现在任务栏上的解决方案时null彼得·弗莱德在 2000 年说

这可能会导致从辅助形式显示的模态形式出现一些问题。

如果用户在模态表单打开时从应用程序切换,然后返回显示它的表单,则模态表单可能会隐藏在表单下方。可以通过确保模态表单是父级来解决这个问题[原文如此;他的意思是拥有] 以显示它的形式( params.WndParent如上使用)

Dialogs但这对于来自单元和异常的标准对话框是不可能的,这需要更多的努力才能让它们正常工作(基本上处理Application.OnActivate,寻找以Application via为父级的模态表单GetLastActivePopup 并将它们带到 Z-order via 的顶部SetWindowPos) .

  • 为什么模态表单最终会卡在其他表单后面?
  • 什么机制通常将模态形式带到前面,为什么它在这里不起作用?
  • Windows® 负责显示堆叠的窗口。Windows® 没有显示正确的窗口出了什么问题?

他还谈到了使用新的 Windows 扩展样式,该样式通过添加扩展样式来强制窗口出现在任务栏上(当使其不拥有的正常规则不足、不切实际或不受欢迎时)WS_EX_APPWINDOW

但随后他警告说:

如果您在另一个应用程序处于活动状态时单击辅助表单任务栏按钮,这仍会将所有应用程序表单置于前面。如果你不希望有选项

当表单的所有者静止时,谁将所有表单带到最前面Application.Handle应用程序是这样做的吗?为什么要这样做?与其这样做,应该这样做吗?这样做有什么缺点?我看到了这样做的缺点(系统菜单无法正常工作,任务栏按钮缩略图不准确,Windows® shell 无法最小化窗口。


在另一篇处理 . 的帖子中ApplicationMike Edenfield 说父窗口向其他窗口发送它们的最小化、最大化和恢复消息

这将为您的表单添加任务栏按钮,但还有一些其他小细节需要处理。最明显的是,您的表单仍然会收到发送到父表单(应用程序的主表单)的最小化/最大化。为了避免这种情况,您可以通过添加如下行来为 WM_SYSCOMMAND 安装消息处理程序:

请注意,此处理程序以您希望独立于应用程序其余部分的行为的PARENT形式出现,以避免传递最小化消息。您可以为 SC_MAXIMIZE、SC_RESTORE 等添加类似的 > 代码。

为什么我的 Windows® 窗口的最小化/最大化/恢复消息没有进入我的窗口?这是因为 Windows® 将发往窗口的消息发送给了窗口的所有者吗?在这种情况下,Delphi 应用程序中的所有表单都是“拥有”的Application?这是否意味着使所有者为空:

将删除Application它的窗口句柄干扰我的表单,Windows 应该再次向我发送的最小化/最大化/恢复消息?


也许如果我们现在比较和对比一个“正常”的 Windows 应用程序做事,与 Borland 最初设计 Delphi 应用程序做事的方式 - 关于这个Application对象和它的主循环。

  • 对象解决的是什么解决方案Application
  • 更高版本的 Delphi 进行了哪些更改以使这些相同的问题不存在?
  • Delphi 后期版本中的更改是否没有引入其他问题,最初的应用程序设计如此努力地解决?
  • 那些较新的应用程序如何在没有应用程序干扰的情况下仍然运行?

显然,Borland 意识到了他们最初设计中的缺陷。他们最初的设计是什么,它解决了什么问题,缺陷是什么,重新设计是什么,它是如何解决问题的?

0 投票
4 回答
5898 浏览

c++ - 为什么标准库有find和find_if?

不能find_if只是超载find吗?朋友也是这样的std::binary_search。。。

0 投票
2 回答
4211 浏览

c++ - 为什么不允许非类型参数中的部分特化使用嵌套模板参数

我有这个代码

也就是说,对于N能被 整除的数字,5编译器应该使用偏特化。但是编译器不会接受这种部分特化,因为标准要求它拒绝这样的代码,其中部分特化的非类型参数引用参数而不是简单的参数(例如,A<N, N>将是有效的)。但是这样做的原因是什么?

请注意,我可以简单地将我的代码更改为更冗长的示例,并且它是有效的

这很好,因为它不再是非类型参数。但是规范禁止更直接的部分专业化的原因是什么?

0 投票
3 回答
382 浏览

c++ - 为什么不 std::set::erase 采用 const_iterator?

看来,根据 ISO 14882 2003(又名 C++ 的神圣标准)std::set<K, C, A>::eraseiterator其作为参数(不是 a const_iterator

从 23.3.3 [2]

void erase(iterator position);

还可能值得注意的是,在我的 VS2008 附带的 STL 实现中,const_iterator当我尝试使用另一个编译器编译我的代码时,erase 会导致令人不快的惊喜。现在,由于我的版本采用 a const_iterator,因此可以使用 a 来实现擦除const_iterator(好像它不是不言而喻的)。

我想标准委员会已经考虑了一些实现(或手头现有的实现),这需要擦除来获取iterator.

  • 如果您同意这种情况,您能否描述一个set::erase需要修改将要删除的元素的实现(我不能)。
  • 如果你不同意,请告诉我为什么他们会做出这个决定?我的意思是,擦除一个元素只是指针的一些重新排列!

编辑

我突然想到,即使在迭代器的情况下,您也无法修改集合中的元素。但问题仍然存在——为什么不使用 const_iterator,尤其是如果它们在某种意义上是等价的

0 投票
2 回答
271 浏览

compiler-construction - 为什么模块在文件中显式命名?

来自D 语言参考

模块与源文件一一对应。模块名是去掉了路径和扩展名的文件名。

但是,模块名称仍然在文件中明确指定。

这有什么意义?如果模块对应于文件,为什么编译器不能从文件名中推断出它们的名称?

0 投票
3 回答
333 浏览

operator-overloading - 为什么 opAssign 不能为类重载?

该表表明,赋值重载仅适用于结构,而不适用于类。这让我很惊讶。句法糖不是A = B无害的吗?将其限制为结构的设计原理是什么?

0 投票
4 回答
81 浏览

java - 为什么不能在重写方法中放宽参数类型?

此代码无效:

因为 everyString显然是 an ,Object所以我希望这段代码非常好:任何依赖于在实际使用.foo()Stringfoo()Object

但是,似乎方法签名必须与它们覆盖的方法的签名相同。为什么?

0 投票
2 回答
1792 浏览

c++ - Why do data() and c_str() return char const*, while operator[] returns char&?

Why do std::string::data and std::string::c_str() return pointers to const chars, while std::string::operator[] returns references to mutable chars?

Why don’t std::string::data() and std::string::c_str() return char*, or why doesn’t std::string::operator[] return char const&?

What is the rationale behind this?