C#编译器要求每当自定义类型定义运算符时==
,它还必须定义!=
(参见此处).
为什么?
我很想知道为什么设计师认为这是必要的,为什么当只有另一个运算符存在时,编译器不能默认为任何一个运算符的合理实现.例如,Lua允许您仅定义相等运算符,而您可以免费获得另一个运算符.C#也可以通过要求你定义==或者两者==和!=然后自动编译缺少的!=运算符来做同样的事情!(left == right)
.
我知道有一些奇怪的角落情况,其中一些实体可能既不平等也不平等(如IEEE-754 NaN),但这些似乎是例外,而不是规则.所以这并不能解释为什么C#编译器设计者将例外规则作为例外.
我已经看到了定义等式运算符的做工不好的情况,然后不等式运算符是一个复制粘贴,每个比较都被反转,每个&&切换到|| (你得到的重点......基本上!(a == b)通过De Morgan的规则扩展).编译器可以通过设计消除这种糟糕的做法,就像Lua的情况一样.
注意:对于运算符<> <=> =也是如此.我无法想象你需要以不自然的方式定义它们的情况.Lua允许您通过前者的否定自然地定义<和<=并定义> =和>.为什么C#不做同样的事情(至少'默认')?
编辑
显然有正当理由允许程序员实现对他们喜欢的平等和不平等的检查.一些答案指向可能很好的情况.
然而,我的问题的核心是为什么在C#中强制要求它通常在逻辑上不必要?
它与.NET接口的设计选择形成鲜明对比,例如Object.Equals
,IEquatable.Equals
IEqualityComparer.Equals
缺少NotEquals
对应物表明框架将!Equals()
对象视为不相等而且就是这样.此外,类Dictionary
和类等方法.Contains()
完全依赖于上述接口,即使定义了运算符也不直接使用运算符.事实上,当ReSharper生成相等成员时,它定义了两者==
并且!=
就其而言,Equals()
即使只是用户选择生成运算符.框架不需要相等运算符来理解对象相等性.
基本上,.NET框架并不关心这些运算符,它只关心几种Equals
方法.要求用户串联定义==和!=运算符的决定纯粹与语言设计有关,而与.NET有关的不是对象语义.
当一个看起来像语义版本的标签被推送时,我想开始一个npm部署,例如v1.2.3
.我看到标签名称在TRAVIS_TAG
环境变量中,我可以指定一个on:
条件,"可以是任何Bash条件".我不知道在这里写什么以及如何调试它.
- provider: npm
on:
tags: true
all_branches: true
condition: ???
理想情况下,我想不打扰Bash - 我希望条件执行Node.js脚本,然后决定是否部署,具体取决于节点退出代码.我怎样才能做到这一点?
让我先从演示开始:
[TestMethod]
public void Test()
{
var h = new WeakReference(new object());
GC.Collect();
Assert.IsNull(h.Target);
}
Run Code Online (Sandbox Code Playgroud)
此代码按预期工作.垃圾收集结束后,引用将h
被取消.现在,这是扭曲:
[TestMethod]
public void Test()
{
var h = new WeakReference(new object());
GC.Collect();
try { } // I just add an empty
finally { } // try/finally block
Assert.IsNull(h.Target); // FAIL!
}
Run Code Online (Sandbox Code Playgroud)
我添加一个空try/finally块来测试后的GC.Collect()
线和LO,弱引用的对象,不收集!如果空的try/finally块加入之前的GC.Collect()
线,测试虽然通过.
是什么赋予了?谁能解释一下try/finally块如何影响对象的生命周期?
注意:所有测试都在Debug中完成.在Release中,两个测试都通过.
注意2:要重现应用程序,必须以.NET 4或.NET 4.5运行时为目标,并且必须以32位运行(目标x86或任何选中"Prefer 32-bit"选项的CPU)
sllauncher.exe具有以下不是非常有用的用法文本:
Usage: SLLauncher.exe [app_id] [debug] [/install:<file path to XAP>]
[/emulate:<file path to XAP>] [/overwrite] /origin:<original app uri>
[/uninstall] [/shortcut:<desktop|startmenu|desktop+startmenu|none>] [/pid]
Run Code Online (Sandbox Code Playgroud)
我对/pid
开关的作用特别感兴趣.我似乎找不到完全记录sllauncher的命令行开关的链接.
我有一个ASP.NET网站,通常通过HTTPS在IIS上运行.现在我想把它放在一个反向代理后面,它会为我做SSL终止.问题是来自反向代理的请求是在HTTP:80上,当我按照惯例创建重定向响应时,响应的Location
标头设置为http://...
而不是https://...
我知道反向代理X-Forwarded-Proto
在标题中传递,我可以在创建重定向响应和重定向URL时检查该标头.但是,如果可能的话,我希望避免为X-Forwarded-Whatever
代码周围的所有内容进行检查,并在编码时再考虑一下,并且还必须仔细检查当代理部署在代理后面时是否仍然有效.
我有一个函数load(std::optional<int> page)
可以加载给定页面或所有页面,如果page.empty()
. 因为加载是一项代价高昂的操作,所以我缓存了最后加载的页面及其内容。为此,我使用了一个成员变量类型,std::optional<std::optional<int>>
它的值应该告诉我当前是否缓存了单个页面、所有页面或根本没有页面。
LLVM 的 libc++ 实现(与 clang 一起提供Apple LLVM version 10.0.0 (clang-1000.11.45.2)
)在比较 std::optional 实例时有一个令人惊讶的行为,这boost::optional
与(用 1.67 测试)不同:
std::cout << (std::optional<int>() == std::optional<std::optional<int>>()); // prints 1
std::cout << (boost::optional<int>() == boost::optional<boost::optional<int>>()); // prints 0
Run Code Online (Sandbox Code Playgroud)
哪个是正确的行为,这是 libc++ 实现中的错误吗?