📜 ⬆️ ⬇️

C #: how to "shoot yourself in the leg"

Consider how you can "shoot yourself in the foot" in C # (and in general in .NET).
It turns out that this can be done not only in C ++.

Below is the code that "plays" with the bool type (System.Boolean) and displays 20 lines True or False on the screen.
For the first ten lines, the behavior is determined only for the first line, and the behavior for 2-10 lines depends on the compiler implementation.

The code is completely self-documented, so I will only add that it is quite possible to stumble upon such behavior when calling unmanaged functions via P / Invoke , in case of their incorrect use (this topic will be continued ).

//#define USE_POINTER_ARITHMETIC_FOR_UNSAFE_MODE using System; using System.Globalization; using System.Runtime.InteropServices; namespace ConsoleApplication { /// <summary> /// Main Program Class /// </summary> static class Program { /// <summary> /// Converts Byte Code to Boolean Value /// </summary> /// <param name="code">Byte Code</param> /// <param name="unsafeMode">Use Unsafe Way to Convert</param> /// <returns>Boolean Value</returns> static bool ByteToBool(byte code, bool unsafeMode) { if (unsafeMode) { #if USE_POINTER_ARITHMETIC_FOR_UNSAFE_MODE // This Code Needs The "/unsafe" Compiler Directive: unsafe { return *(bool*)&code; } #else // This Code No Needs The "/unsafe" Compiler Directive: return (new UnsafeBool() { Code = code }).Value; #endif } return code != 0; // Safe Way } /// <summary> /// Itz a "Funny" Bool Joke! /// </summary> static void BoolJoke(Action<string> output) { int row = 0; Func<string> getNextRow = () => string.Format(NumberFormatInfo.InvariantInfo, "{0:00}: ", ++row); for (int i = 0; i < 2; i++) { bool isUnsafeMode = i == 0; output(isUnsafeMode ? "Unsafe Mode" : "Safe Mode"); bool b1 = true; // Internal Code: 1 (Implementation-Dependent, Undocumented) bool b2 = ByteToBool(0xFF, isUnsafeMode); // Value is Invalid bool b3 = ByteToBool(0xFE, isUnsafeMode); // Value is Invalid output(getNextRow() + "b1 : " + b1); output(getNextRow() + "b2 : " + b2); output(getNextRow() + " b1 == b2: " + (b1 == b2)); output(getNextRow() + "!b1 == !b2: " + (!b1 == !b2)); output(getNextRow() + "b1 && b2 : " + (b1 && b2)); output(getNextRow() + "b1 & b2 : " + (b1 & b2)); output(getNextRow() + "b1 ^ b2 : " + (b1 ^ b2)); output(getNextRow() + "b1 && b3 : " + (b1 && b3)); output(getNextRow() + "b1 & b3 : " + (b1 & b3)); output(getNextRow() + "b1 ^ b3 : " + (b1 ^ b3)); output(null); } } /// <summary> /// Application Entry Point /// </summary> static void Main() { BoolJoke(Console.WriteLine); Console.ReadKey(); // Press Any Key to Exit } } /// <summary> /// Unsafe Boolean Structure /// </summary> /// <remarks> /// See https://msdn.microsoft.com/library/c8f5xwh7.aspx /// See https://msdn.microsoft.com/library/eahchzkf.aspx /// </remarks> [StructLayout(LayoutKind.Explicit)] struct UnsafeBool { /// <summary> /// Boolean Value /// </summary> [FieldOffset(0)] public bool Value; /// <summary> /// Boolean Value Internal Code /// </summary> [FieldOffset(0)] public byte Code; } } 

')

Source: https://habr.com/ru/post/252357/


All Articles