小编Jep*_*sen的帖子

数学解释为什么Decimal转换为Double并且Decimal.GetHashCode分隔相等的实例

我不确定这种说明Stack Overflow问题的非标准方式是好还是坏,但是这里是:

什么是最好的(数学或其他技术)解释为什么代码:

static void Main()
{
  decimal[] arr =
  {
    42m,
    42.0m,
    42.00m,
    42.000m,
    42.0000m,
    42.00000m,
    42.000000m,
    42.0000000m,
    42.00000000m,
    42.000000000m,
    42.0000000000m,
    42.00000000000m,
    42.000000000000m,
    42.0000000000000m,
    42.00000000000000m,
    42.000000000000000m,
    42.0000000000000000m,
    42.00000000000000000m,
    42.000000000000000000m,
    42.0000000000000000000m,
    42.00000000000000000000m,
    42.000000000000000000000m,
    42.0000000000000000000000m,
    42.00000000000000000000000m,
    42.000000000000000000000000m,
    42.0000000000000000000000000m,
    42.00000000000000000000000000m,
    42.000000000000000000000000000m,
  };

  foreach (var m in arr)
  {
    Console.WriteLine(string.Format(CultureInfo.InvariantCulture,
      "{0,-32}{1,-20:R}{2:X8}", m, (double)m, m.GetHashCode()
      ));
  }

  Console.WriteLine("Funny consequences:");
  var h1 = new HashSet<decimal>(arr);
  Console.WriteLine(h1.Count);
  var h2 = new HashSet<double>(arr.Select(m => (double)m));
  Console.WriteLine(h2.Count);
}
Run Code Online (Sandbox Code Playgroud)

给出以下"有趣"(显然不正确)的输出:

42                              42                  40450000
42.0                            42                  40450000
42.00                           42                  40450000 …

.net c# floating-point decimal base-class-library

23
推荐指数
2
解决办法
592
查看次数

为什么'unbox.any'没有像'castclass'那样提供有用的异常文本?

为了说明我的问题,请考虑这些简单的例子(C#):

object reference = new StringBuilder();
object box = 42;
object unset = null;

// CASE ONE: bad reference conversions (CIL instrcution 0x74 'castclass')
try
{
  string s = (string)reference;
}
catch (InvalidCastException ice)
{
  Console.WriteLine(ice.Message); // Unable to cast object of type 'System.Text.StringBuilder' to type 'System.String'.
}
try
{
  string s = (string)box;
}
catch (InvalidCastException ice)
{
  Console.WriteLine(ice.Message); // Unable to cast object of type 'System.Int32' to type 'System.String'.
}

// CASE TWO: bad unboxing conversions (CIL instrcution …
Run Code Online (Sandbox Code Playgroud)

.net c# clr unboxing cil

23
推荐指数
1
解决办法
691
查看次数

为什么编译器会评估与运行时不同的余数MinValue%-1?

我认为这看起来像C#编译器中的一个错误.

考虑这段代码(在方法内):

const long dividend = long.MinValue;
const long divisor = -1L;
Console.WriteLine(dividend % divisor);
Run Code Online (Sandbox Code Playgroud)

它编译时没有错误(或警告).好像是一个bug.运行时,0在控制台上打印.

然后没有const,代码:

long dividend = long.MinValue;
long divisor = -1L;
Console.WriteLine(dividend % divisor);
Run Code Online (Sandbox Code Playgroud)

当它运行时,它正确地导致OverflowException被抛出.

C#语言规范专门提到了这个案例,并说System.OverflowException将抛出一个.它不依赖于上下文checkedunchecked似乎(也是与余数运算符的编译时常量操作数的错误与checked和相同unchecked).

int(System.Int32),而不仅仅是long(System.Int64)发生同样的错误.

相比之下,编译器处理dividend / divisorconst操作数比要好得多dividend % divisor.

我的问题:

我是对的,这是一个错误吗?如果是,它是一个众所周知的错误,他们不希望修复(因为向后兼容性,即使使用% -1编译时常量相当愚蠢-1)?或者我们应该报告它,以便他们可以在即将推出的C#编译器版本中修复它?

c# operators overflowexception compiler-bug modulus

22
推荐指数
1
解决办法
538
查看次数

为什么类型System .__ ComObject声称(有时)不公开?

只是奇怪的是,当我反思所有类型时,我偶然发现了好奇心来检查其他东西.

为什么System.__ComObject集会的阶级mscorlib.dll(有时?)声称是公开的,而事实上它似乎是非公开的?如果我在一个简单的C#控制台应用程序中运行以下代码:

var t = Type.GetType("System.__ComObject");
Console.WriteLine(t.IsPublic);   // "True"   ?!
Console.WriteLine(t.IsVisible);  // "False"
Run Code Online (Sandbox Code Playgroud)

输出似乎有冲突.非嵌套类型(t.IsNested为false)应为IsPublic和提供相同的真值IsVisible.当我看到装配时,IL DASM我看到:

.class private auto ansi beforefieldinit System.__ComObject
       extends System.MarshalByRefObject
{
} // end of class System.__ComObject
Run Code Online (Sandbox Code Playgroud)

对我来说,它看起来非常像非公开类,这些对应于下面的C#代码:

namespace System
{
    // not public
    internal class __ComObject : MarshalByRefObject
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

当我比较其他类型的具有类似的名称,System.__Canon以及类似IL改性剂,既IsPublicIsVisible预期返回false.

有谁知道为什么(和什么时候)Type.GetType("System.__ComObject").IsPublic给出了真实的?

.net c# reflection encapsulation cil

20
推荐指数
1
解决办法
2628
查看次数

使用泛型语法的反射在重写方法的返回参数上失败

为了避免在搜索已知类型的属性时使用过时的非泛型语法,通常会使用System.Reflection.CustomAttributeExtensions类中的扩展方法(从.NET 4.5开始).

但是,如果在重写方法的返回参数(或重写的属性/索引器的访问者)上搜索属性,则这似乎会失败.

我正在使用.NET 4.6.1体验这一点.

简单复制(完整):

using System;
using System.Reflection;

namespace ReflectionTrouble
{
  class B
  {
    //[return: MyMark("In base class")] // uncommenting does not help
    public virtual int M() => 0;
  }

  class C : B
  {
    [return: MyMark("In inheriting class")] // commenting away attribute does not help
    public override int M() => -1;
  }

  [AttributeUsage(AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = false)] // commenting away AttributeUsage does not help
  sealed class MyMarkAttribute : Attribute
  { …
Run Code Online (Sandbox Code Playgroud)

.net c# reflection custom-attributes base-class-library

20
推荐指数
1
解决办法
502
查看次数

为什么ᏌᏊᎢᏳᎾᎵᏍᏔᏅᏍᎦᏚᎩ是美国的本土名称?

当我使用这段代码时:

var ri = new RegionInfo("us");
var nativeName = ri.NativeName;   // ?? ??????? ????
Run Code Online (Sandbox Code Playgroud)

nativeName那么为什么是弦乐"?? ??????? ????"(在切罗基)?

如果我改为new RegionInfo("US")(只有差异,资本US),我会改为"United States".

知道的首选使用的RegionInfo是给特定的文化信息字符串,例如:

new RegionInfo("en-US")
new RegionInfo("chr-Cher-US")
Run Code Online (Sandbox Code Playgroud)

等等,这是有效的.但是,只有当我使用小写时,为什么切诺基比英语更喜欢us


(见于Windows 10(版本1803"2018年4月更新"),.NET Framework 4.7.2.)


更新:即使在同一台机器上,这也不一致.例如,我尝试打开PowerShell很多次,每次粘贴[System.Globalization.RegionInfo]'US'它.好像很长一段时间,PowerShell的所有实例都始终给出相同的结果.但过了一会儿,PowerShell的实例会产生相反的结果.这是两个窗口的屏幕截图,一个窗口始终有一个窗口,另一个窗口NativeName始终具有相反的窗口.因此必须有一些非确定性的决定(套管无差异):

PowerShell窗口

.net c# globalization regioninfo casing

20
推荐指数
1
解决办法
398
查看次数

密封关键字会影响编译器对强制转换的看法

我有一种情况,我喜欢编译器的行为解释.给出一点代码:

interface IFoo<T>
{
    T Get();
}

class FooGetter : IFoo<int>
{
    public int Get()
    {
        return 42;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下编译并运行:

static class FooGetterGetter
{
    public static IFoo<T> Get<T>()
    {
        return (IFoo<T>)new FooGetter();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我们更改Foo类的签名并添加sealed关键字:

sealed class FooGetter : IFoo<int> // etc
Run Code Online (Sandbox Code Playgroud)

然后我在以下行得到编译器错误:

 return (IFoo<T>)new FooGetter();
Run Code Online (Sandbox Code Playgroud)

的:

无法将类型'MyNamespace.FooGetter'转换为'MyNamespace.IFoo <T>'

有人可以解释sealed关键字的问题吗?这是针对Visual Studio 2010中的.NET 4项目的C#4.

更新:有趣的是,当我想知道为什么以下代码在sealed应用时修复它时,我偶然发现了这部分行为:

return (IFoo<T>)(IFoo<int>)new FooGetter();
Run Code Online (Sandbox Code Playgroud)

更新:只是为了澄清,当T请求的类型T与具体类型使用的类型相同时,它都运行良好.如果类型不同,则转换在运行时失败,例如:

无法将"MyNamespace.StringFoo"类型的对象强制转换为"MyNamespace.IFoo"1 [System.Int32]'

在上面的示例中,StringFoo : IFoo<string>调用者要求获取 …

c# compiler-errors visual-studio-2010

19
推荐指数
1
解决办法
464
查看次数

为什么属性目标'typevar'没有文档?

众所周知,在C#中,可以指定自定义属性规范的目标,如示例中所示

[method: SomeDecoration]
[return: SomeOtherMark]
int MyMethod();
Run Code Online (Sandbox Code Playgroud)

其中"targets" method:return:帮助指定属性所属的代码中的哪个元素.

根据C#语言规范,存在以下属性目标:

  • 全球性的:
    • assembly
    • module
  • 其他:
    • field
    • event
    • method
    • param
    • property
    • return
    • type

其中一些,如同field,总是多余的,因为它总是很清楚属性"坐在"而没有指定它们.

但是确实存在(至少在Visual C#的实现和版本中我在这里)一个额外的属性目标,即:

  • typevar

例如在代码中允许的

class MyGenericCollection<[typevar: HereYouSee] TItem>    // legal
{
}
Run Code Online (Sandbox Code Playgroud)

属性目标typevar,就像field其他人一样,永远不需要.

我的问题:有没有人知道typevar:规范或文档中没有提到的历史原因?当编写2.0版本的C#语言规范时,这个被遗忘了吗?或者,如果不是疏忽,为什么要实施呢?

c# attributes

19
推荐指数
1
解决办法
412
查看次数

为什么在接口列表中的泛型类型中使用私有嵌套类型不是"不一致的可访问性"?

如果标题不完全不言自明,这里的代码让我困惑:

public interface IFoo<T>
{
}

public class MyClass : IFoo<MyClass.NestedInMyClass>
{
  private class NestedInMyClass
  {
  }
}
Run Code Online (Sandbox Code Playgroud)

我很惊讶这个编译没有错误.感觉就像我暴露了一种private类型.这不应该是违法的吗?

也许你的回答只是"没有规则反对,所以为什么不行呢?" MyClass.NestedInMyClass即使在"范围"中也许同样令人惊讶.如果我删除了MyClass.资格,它将无法编译.

(如果我改为IFoo<>通用,它应该成为基类MyClass,这非法的,因为基类型必须至少与类型本身一样可访问.)

我尝试使用Visual Studio 2010的C#4编译器.

c# generics encapsulation access-modifiers

18
推荐指数
1
解决办法
281
查看次数

.NET枚举类型实际上是可变的值类型吗?

通过反射,在枚举类型的字段中查看,我惊讶地发现,保留枚举的特定实例的实际值的"支持"实例字段不是private,正如我所想的那样,但是public.它也不readonly是.(IsPublic是的,IsInitOnly假的.)

许多人认为.NET类型系统中的"可变"值类型"邪恶",那么为什么枚举类型(例如从C#代码创建)就是这样?

现在,事实证明,C#编译器有某种魔法否认公共实例字段的存在(但见下文),但在例如PowerShell中你可以这样做:

prompt> $d = [DayOfWeek]::Thursday
prompt> $d
Thursday
prompt> $d.value__ = 6
prompt> $d
Saturday
Run Code Online (Sandbox Code Playgroud)

该字段value__可以写入.

现在,要在C#中执行此操作,我必须使用,dynamic因为看起来使用正常的编译时成员绑定,C#假装public实例字段不存在.当然要使用dynamic,我们将不得不使用枚举值的装箱.

这是一个C#代码示例:

// create a single box for all of this example
Enum box = DayOfWeek.Thursday;

// add box to a hash set
var hs = new HashSet<Enum> { box, };

// make a dynamic reference to the same …
Run Code Online (Sandbox Code Playgroud)

.net c# powershell enums immutability

17
推荐指数
1
解决办法
1673
查看次数