在C#中有趣的类型系统冲突(在安全的前提下)冲突、有趣、类型、前提下

2023-09-04 00:57:41 作者:你是年少的欢喜

该类型系统侵犯我说说 - 是模仿工会时

为什么在安全的前提下允许的?

它可以让您处理值类型,不同的值类型 - 因为你将与实现的:

浮动F = 2.5F; INT binaryIdenticalInt = *((INT *)及F);

它可以让你引用类型X的对象,因为它是Y型的,即使有这些类型之间没有什么关系。

它允许你创建类型该CLR甚至不用加载(如果重叠的领域至少有一个是引用类型,而其中至少有一个是价值/指针类型 - 在CLR会拒绝加载)。我希望C#编译器更加挑剔,它允许,比CLR。而不是更少。

那么,为什么编译器还允许在首位在安全的前提下这样的事情?为什么它不要求不安全上下文有明确的布局类型,其中有重叠的领域?

我希望有人在那里有一个答案 - 因为它必须是有趣的。

例子(所有编译没有不安全的块,甚至也不是不安全的开关):

  [StructLayout(LayoutKind.Explicit)
结构ValueUnion
{
    [FieldOffset(0)]
    公众诠释我;

    [FieldOffset(0)]
    公众持股量F;
}

[StructLayout(LayoutKind.Explicit)
结构ReferenceUnion
{
    [FieldOffset(0)]
    公共字符串str;

    [FieldOffset(0)]
    公共流流;
}

[StructLayout(LayoutKind.Explicit)
结构CLRWontLoad
{
    [FieldOffset(0)]
    公共字符串str;

    [FieldOffset(0)]
    公共IntPtr的PTR;
}
 

解决方案

让我回答一些稍有不同的问题。

  

是否使用显式布局属性允许违反类型安全的,而无需使用不安全关键字?

是的。这就是它了。

  

该编译器有什么 FieldOffset 属性的认识?

编译器验证 FieldOffset 属性不是静态/常量领域,它与 StructLayout 属性。它不检查任何其他有关属性的有效性。

  

为什么C#编译器检测不到属性的潜在的不安全使用,并要求不安全关键字?

难道W7 系统 不好玩单击游戏吗 怎么我下的单击游戏都没反应啊

这是一个功能。为了能够使用你,一个功能必须被认为是,设计,指定,实现,测试,记录并运送给客户。此功能被认为的。它不是设计,规定,实施,测试,文档,或运,因此也没有这样的功能。

  

这是一个不令人满意的答案。

我的建议是不要问关于计算器为什么的问题。 为什么的问题是模糊的,因此,你经常会得到不令人满意的答案。 为什么不的问题是更难satisfactorilly回答,因为他们有presupposition有需要为世界不是一种方式,它是不是一个很好的理由。

  

OK,让我改一下。如果此功能被投给编译器的设计团队,什么利弊可能他们考虑作出决定时是否继续进行该功能?

临:在code可以清晰地以不安全的方式使用,因此应要求不安全关键字,允许它

缺点:在不安全关键字是那里prevent的偶然的使用危险不安全的特点,功能,四十年的C已经告诉我们,即使是专业程序员做出难以发现错误。有没有办法的意外的使用结构布局属性。有人谁使用这个属性可以假定知道$ P $他们在做什么pcisely,并有很好的理由,他们在做什么。

在我看来,在这里缺点大于优点。该功能将是一个合理的成本非常小的好处。

记住,落实每一项功能意味着名单上的其他功能的没有的实施,因为预算是有限的。我不希望做到这一点微弱的特点,不得不削减一个功能,真正受益的开发者。

  

考虑了该功能的小组,并拒绝了它基于这些理由?

是的。请参见

http://connect.microsoft.com/VisualStudio/feedback/details/357828/using-explicit-struct-layout-causes-compiler-to-produce-unverifiable-$c$c

The type system violation which I talk about - is when emulating unions.

Why is it allowed in safe context?

It allows you to handle value types, as different value type - as you would achieve with:

float f = 2.5f; int binaryIdenticalInt = *((int*)&f);

It allows you to reference an object of type X, as it was of type Y, EVEN WHEN THERE IS NO RELATION BETWEEN THOSE TYPES.

It allows you to create types which the CLR won't even load (if at least one of overlapping fields is a reference type, and at least one of them is value/pointer type - the CLR would refuse to load it). I would expect the C# compiler to be more picky about what it allows, than the CLR. not less.

So, why the compiler allow such things in safe context in the first place? Why doesn't it require unsafe context for types with explicit layout, which have overlapping fields?

I hope someone out there has an answer - because it has to be interesting.

Examples (all compiled without unsafe block, nor even unsafe switch):

[StructLayout(LayoutKind.Explicit)]
struct ValueUnion
{
    [FieldOffset(0)]
    public int i;

    [FieldOffset(0)]
    public float f;
}

[StructLayout(LayoutKind.Explicit)]
struct ReferenceUnion
{
    [FieldOffset(0)]
    public string str;

    [FieldOffset(0)]
    public Stream stream;
}

[StructLayout(LayoutKind.Explicit)]
struct CLRWontLoad
{
    [FieldOffset(0)]
    public string str;

    [FieldOffset(0)]
    public IntPtr ptr;
}

解决方案

Let me answer some slightly different questions.

Does using the explicit layout attribute allow violations of type safety without using the unsafe keyword?

Yes. That's what it's for.

What knowledge of the FieldOffset attribute does the compiler have?

The compiler verifies that the FieldOffset attribute is not on static / const fields and that it is consistent with the StructLayout attribute. It does not check anything else about the validity of the attribute.

Why does the C# compiler not detect a potentially unsafe usage of the attribute and require the unsafe keyword?

That's a feature. In order to be used by you, a feature must be thought of, designed, specified, implemented, tested, documented and shipped to customers. This feature was thought of. It was not designed, specified, implemented, tested, documented, or shipped, and therefore there is no such feature.

That's an unsatisfying answer.

My advice is to not ask "why" questions on StackOverflow. "Why" questions are vague, and therefore you often get unsatisfying answers. "Why not" questions are even harder to answer satisfactorilly because they have the presupposition that there needs to be a good reason for the world to not be a way that it isn't.

OK, let me rephrase. If this feature were pitched to the compiler design team, what pros and cons might they consider when deciding whether to proceed with the feature?

Pro: the code can clearly be used in an unsafe manner, and so should require the unsafe keyword to allow it.

Con: the unsafe keyword is there to prevent accidental use of dangerously unsafe features, feature which four decades of C has shown us that even expert programmers make hard-to-find mistakes. There is no way to accidentally use the struct layout attribute. Someone who uses this attribute can be assumed to know precisely what they're doing, and have a good reason for what they're doing.

In my opinion, the cons outweigh the pros here. The feature would be a very small benefit for a moderate cost.

Remember, every feature implemented means another feature on the list not implemented, because the budget is finite. I would not want to do this weak feature and have to cut a feature that actually benefited developers.

Has the team considered this feature and rejected it on these grounds?

Yes. See

http://connect.microsoft.com/VisualStudio/feedback/details/357828/using-explicit-struct-layout-causes-compiler-to-produce-unverifiable-code

 
精彩推荐
图片推荐