Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';这是你遇到的最奇怪的情况;你在C#或.NET中见过吗?_C#_.net - Fatal编程技术网

什么';这是你遇到的最奇怪的情况;你在C#或.NET中见过吗?

什么';这是你遇到的最奇怪的情况;你在C#或.NET中见过吗?,c#,.net,C#,.net,我收集了一些角落里的箱子,希望能听到更多。该页面只涵盖了C#语言和BOB,但我也发现核心.NET内容也很有趣。例如,有一个页面上没有,但我觉得不可思议: string x = new string(new char[0]); string y = new string(new char[0]); Console.WriteLine(object.ReferenceEquals(x, y)); 我希望打印False——毕竟,“new”(带有引用类型)总是创建一个新对象,不是吗?C#和CLI的规范

我收集了一些角落里的箱子,希望能听到更多。该页面只涵盖了C#语言和BOB,但我也发现核心.NET内容也很有趣。例如,有一个页面上没有,但我觉得不可思议:

string x = new string(new char[0]);
string y = new string(new char[0]);
Console.WriteLine(object.ReferenceEquals(x, y));
我希望打印False——毕竟,“new”(带有引用类型)总是创建一个新对象,不是吗?C#和CLI的规范都表明它应该。嗯,在这个特殊的情况下没有。它打印的是真的,并且在我测试过的框架的每个版本上都做过。(无可否认,我还没有在Mono上试过……)

说清楚一点,这只是我正在寻找的一个例子——我并不是特别想要讨论/解释这种奇怪的现象。(这与普通的字符串内部处理不同;特别是,调用构造函数时通常不会发生字符串内部处理。)我真的要求类似的奇怪行为


还有其他的宝藏吗?

我想我以前给你看过这个,但我喜欢这里的乐趣-这需要一些调试才能找到!(原始代码显然更加复杂和微妙…)

但是它可以被打败!使用与远程处理相同的间接方式;警告-以下是纯粹的邪恶:

class MyFunnyProxyAttribute : ProxyAttribute {
    public override MarshalByRefObject CreateInstance(Type serverType) {
        return null;
    }
}
[MyFunnyProxy]
class MyFunnyType : ContextBoundObject { }
有了这个选项,
new()
调用被重定向到代理(
MyFunnyProxyAttribute
),该代理返回
null
。现在去洗你的眼睛

Public Class Item
   Public ID As Guid
   Public Text As String

   Public Sub New(ByVal id As Guid, ByVal name As String)
      Me.ID = id
      Me.Text = name
   End Sub
End Class

Public Sub Load(sender As Object, e As EventArgs) Handles Me.Load
   Dim box As New ComboBox
   Me.Controls.Add(box)          'Sorry I forgot this line the first time.'
   Dim h As IntPtr = box.Handle  'Im not sure you need this but you might.'
   Try
      box.Items.Add(New Item(Guid.Empty, Nothing))
   Catch ex As Exception
      MsgBox(ex.ToString())
   End Try
End Sub
输出为“试图读取受保护内存。这表示其他内存已损坏。”

这一个并不是一个编译器错误或故障,但肯定是一个奇怪的角落情况

Net框架采用一种称为银行家舍入的方案或舍入

在银行家的四舍五入中,0.5的数字被四舍五入到最接近的偶数,因此

Math.Round(-0.5) == 0
Math.Round(0.5) == 0
Math.Round(1.5) == 2
Math.Round(2.5) == 2
etc...
这可能会导致基于更广为人知的舍入-半向上舍入的财务计算出现一些意想不到的错误


VisualBasic也是如此。

有趣的是,当我第一次看到它时,我假设它是C#编译器正在检查的东西,但即使您直接发出IL以消除任何干扰机会,它仍然会发生,这意味着执行检查的确实是
newobj
操作代码

var method = new DynamicMethod("Test", null, null);
var il = method.GetILGenerator();

il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Newarr, typeof(char));
il.Emit(OpCodes.Newobj, typeof(string).GetConstructor(new[] { typeof(char[]) }));

il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Newarr, typeof(char));
il.Emit(OpCodes.Newobj, typeof(string).GetConstructor(new[] { typeof(char[]) }));

il.Emit(OpCodes.Call, typeof(object).GetMethod("ReferenceEquals"));
il.Emit(OpCodes.Box, typeof(bool));
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new[] { typeof(object) }));

il.Emit(OpCodes.Ret);

method.Invoke(null, null);

如果您检查
字符串,则它也等同于
true
。Empty
,这意味着此操作代码必须具有特殊的行为来插入空字符串。

布尔值何时既不为true也不为False?

比尔发现你可以破解一个布尔值,这样如果a为真,B为真,(a和B)为假


如果此函数被称为
Rec(0)
(不在调试器下),它将做什么

静态无效记录(int i)
{
控制台写入线(i);
if(i
答复:

  • 在32位JIT上,它应该导致StackOverflowException
  • 在64位JIT上,它应该将所有数字打印为int.MaxValue
这是因为,而32位JIT没有

不幸的是,我手头没有64位机器来验证这一点,但该方法确实满足尾部调用优化的所有条件。如果有人真的有,我很想知道这是不是真的。

C#支持数组和列表之间的转换,只要数组不是多维的,并且类型之间存在继承关系,并且类型是引用类型

object[] oArray = new string[] { "one", "two", "three" };
string[] sArray = (string[])oArray;

// Also works for IList (and IEnumerable, ICollection)
IList<string> sList = (IList<string>)oArray;
IList<object> oList = new string[] { "one", "two", "three" };

我去派对晚了一点,但我有三四五个:

  • 如果您在尚未加载/显示的控件上轮询InvokeRequired,它将显示false-如果您尝试从另一个线程更改它,它将显示false-并在您面前爆炸(是引用控件创建者中的此.Handle)

  • 另一个让我大吃一惊的问题是,给了一个组件:

    enum MyEnum
    {
        Red,
        Blue,
    }
    
    如果您在另一个程序集中计算MyEnum.Red.ToString(),并且在这段时间内有人将您的枚举重新编译为:

    enum MyEnum
    {
        Black,
        Red,
        Blue,
    }
    
    在运行时,您将得到“黑色”

  • 我有一个共享程序集,其中包含一些方便的常量。我的前任留下了一大堆难看的get only属性,我想我应该摆脱混乱,只使用public const。当VS将它们编译为它们的值而不是引用时,我感到非常惊讶

  • 如果从另一个程序集实现接口的新方法,但重新生成时引用该程序集的旧版本,则会得到TypeLoadException(“NewMethod”)的实现,即使您已经实现了它(请参阅)

  • 字典:“返回项目的顺序未定义”。这是可怕的,因为它有时会咬你,但会影响其他人,如果你只是盲目地认为字典会很好用(“为什么不应该呢?我想,列表会”),那么在你最终开始质疑你的假设之前,你真的必须要管好自己的鼻子


  • 下面是一个示例,说明如何创建导致错误消息“试图读取或写入受保护内存。这通常表示其他内存已损坏”的结构。 成功和失败之间的区别是非常微妙的

    下面的单元测试演示了这个问题

    看看你能不能找出哪里出了问题

        [Test]
        public void Test()
        {
            var bar = new MyClass
            {
                Foo = 500
            };
            bar.Foo += 500;
    
            Assert.That(bar.Foo.Value.Amount, Is.EqualTo(1000));
        }
    
        private class MyClass
        {
            public MyStruct? Foo { get; set; }
        }
    
        private struct MyStruct
        {
            public decimal Amount { get; private set; }
    
            public MyStruct(decimal amount) : this()
            {
                Amount = amount;
            }
    
            public static MyStruct operator +(MyStruct x, MyStruct y)
            {
                return new MyStruct(x.Amount + y.Amount);
            }
    
            public static MyStruct operator +(MyStruct x, decimal y)
            {
                return new MyStruct(x.Amount + y);
            }
    
            public static implicit operator MyStruct(int value)
            {
                return new MyStruct(value);
            }
    
            public static implicit operator MyStruct(decimal value)
            {
                return new MyStruct(value);
            }
        }
    

    几年前,当我们致力于忠诚计划时,我们对给予客户的积分数量存在问题。该问题与将double转换为int有关

    代码如下:

    double d = 13.6;
    
    int i1 = Convert.ToInt32(d);
    int i2 = (int)d;
    
    i1==i2吗

    结果是i1!=i2。 由于Convert和cast运算符中的舍入策略不同,实际值为:

    i1 == 14
    i2 == 13
    
    最好调用Math.天花()或Math.Floor()(或者使用满足我们要求的中点舍入的Math.Round)


    即使存在枚举函数,它们也应该将0设置为整数
    enum MyEnum
    {
        Black,
        Red,
        Blue,
    }
    
        [Test]
        public void Test()
        {
            var bar = new MyClass
            {
                Foo = 500
            };
            bar.Foo += 500;
    
            Assert.That(bar.Foo.Value.Amount, Is.EqualTo(1000));
        }
    
        private class MyClass
        {
            public MyStruct? Foo { get; set; }
        }
    
        private struct MyStruct
        {
            public decimal Amount { get; private set; }
    
            public MyStruct(decimal amount) : this()
            {
                Amount = amount;
            }
    
            public static MyStruct operator +(MyStruct x, MyStruct y)
            {
                return new MyStruct(x.Amount + y.Amount);
            }
    
            public static MyStruct operator +(MyStruct x, decimal y)
            {
                return new MyStruct(x.Amount + y);
            }
    
            public static implicit operator MyStruct(int value)
            {
                return new MyStruct(value);
            }
    
            public static implicit operator MyStruct(decimal value)
            {
                return new MyStruct(value);
            }
        }
    
    double d = 13.6;
    
    int i1 = Convert.ToInt32(d);
    int i2 = (int)d;
    
    i1 == 14
    i2 == 13
    
    int i1 = Convert.ToInt32( Math.Ceiling(d) );
    int i2 = (int) Math.Ceiling(d);
    
    namespace Craft
    {
        enum Symbol { Alpha = 1, Beta = 2, Gamma = 3, Delta = 4 };
    
    
       class Mate
        {
            static void Main(string[] args)
            {
    
                JustTest(Symbol.Alpha); // enum
                JustTest(0); // why enum
                JustTest((int)0); // why still enum
    
                int i = 0;
    
                JustTest(Convert.ToInt32(0)); // have to use Convert.ToInt32 to convince the compiler to make the call site use the object version
    
                JustTest(i); // it's ok from down here and below
                JustTest(1);
                JustTest("string");
                JustTest(Guid.NewGuid());
                JustTest(new DataTable());
    
                Console.ReadLine();
            }
    
            static void JustTest(Symbol a)
            {
                Console.WriteLine("Enum");
            }
    
            static void JustTest(object o)
            {
                Console.WriteLine("Object");
            }
        }
    }
    
    if (true)
    {
       OleDbCommand command = SQLServer.CreateCommand();
    }
    
    OleDbCommand command = SQLServer.CreateCommand();
    
    interface IFoo
    {
       string Message {get;}
    }
    ...
    IFoo obj = new IFoo("abc");
    Console.WriteLine(obj.Message);
    
    public class Turtle<T> where T : Turtle<T>
    {
    }
    
    stringvariable1.Equals(stringvariable2, StringComparison.InvariantCultureIgnoreCase);
    
    if (assemblyfilename.EndsWith("someparticular.dll", StringComparison.InvariantCultureIgnoreCase))
    {
        assemblyfilename = "someparticular_modified.dll";
    }
    
    Dim i As Integer? = If(True, Nothing, 5)
    
    enumProperty.SetValue(obj, 1, null); //works
    nullableIntProperty.SetValue(obj, 1, null); //works
    nullableEnumProperty.SetValue(obj, MyEnum.Foo, null); //works
    nullableEnumProperty.SetValue(obj, 1, null); // throws an exception !!!
    
        public void Foo()
        {
            this = new Teaser();
        }
    
    string cheat = @"
        public void Foo()
        {
            this = new Teaser();
        }
    ";
    
    public struct Teaser
    {
        public void Foo()
        {
            this = new Teaser();
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Derived d = new Derived();
            d.Property = "AWESOME";
        }
    }
    
    class Base
    {
        string _baseProp;
        public virtual string Property 
        { 
            get 
            {
                return "BASE_" + _baseProp;
            }
            set
            {
                _baseProp = value;
                //do work with the base property which might 
                //not be exposed to derived types
                //here
                Console.Out.WriteLine("_baseProp is BASE_" + value.ToString());
            }
        }
    }
    
    class Derived : Base
    {
        string _prop;
        public override string Property 
        {
            get { return _prop; }
            set 
            { 
                _prop = value; 
                base.Property = value;
            } //<- put a breakpoint here then mouse over BaseProperty, 
              //   and then mouse over the base.Property call inside it.
        }
    
        public string BaseProperty { get { return base.Property; } private set { } }
    }
    
    ((TestProject1.Base)(d))
    
    public string BaseProperty { get { return ((TestProject1.Base)(d)).Property; } private set { } }
    
    string filename = @"c:\program files\my folder\test.txt";
    System.IO.File.WriteAllText(filename, "Hello world.");
    bool exists = System.IO.File.Exists(filename); // returns true;
    string text = System.IO.File.ReadAllText(filename); // Returns "Hello world."
    
    public class DummyObject
    {
        public override string ToString()
        {
            return null;
        }
    }
    
    DummyObject obj = new DummyObject();
    Console.WriteLine("The text: " + obj.GetType() + " is " + obj);
    
    object obj2 = args[i];
    string text = (obj2 != null) ? obj2.ToString() : string.Empty;
    // if obj2 is non-null, but obj2.ToString() returns null, then text==null
    int length = text.Length;
    
    Bool aBoolValue;
    
    Byte aByteValue = aBoolValue ? 1 : 0;
    
    Int anIntValue = aBoolValue ? 1 : 0;
    
    interface I<T> {
      T M(T p);
    }
    abstract class A<T> : I<T> {
      public abstract T M(T p);
    }
    abstract class B<T> : A<T>, I<int> {
      public override T M(T p) { return p; }
      public int M(int p) { return p * 2; }
    }
    class C : B<int> { }
    
    class Program {
      static void Main(string[] args) {
        Console.WriteLine(new C().M(42));
      }
    }
    
    C:\Temp>type Program.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1 {
    
      interface I<T> {
        T M(T p);
      }
      abstract class A<T> : I<T> {
        public abstract T M(T p);
      }
      abstract class B<T> : A<T>, I<int> {
        public override T M(T p) { return p; }
        public int M(int p) { return p * 2; }
      }
      class C : B<int> { }
    
      class Program {
        static void Main(string[] args) {
          Console.WriteLine(new C().M(11));
        }
      }
    
    }
    C:\Temp>csc Program.cs
    Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
    for Microsoft (R) .NET Framework version 3.5
    Copyright (C) Microsoft Corporation. All rights reserved.
    
    
    C:\Temp>Program
    
    Unhandled Exception: System.TypeLoadException: Could not load type 'ConsoleAppli
    cation1.C' from assembly 'Program, Version=0.0.0.0, Culture=neutral, PublicKeyTo
    ken=null'.
       at ConsoleApplication1.Program.Main(String[] args)
    
    C:\Temp>peverify Program.exe
    
    Microsoft (R) .NET Framework PE Verifier.  Version  3.5.30729.1
    Copyright (c) Microsoft Corporation.  All rights reserved.
    
    [token  0x02000005] Type load failed.
    [IL]: Error: [C:\Temp\Program.exe : ConsoleApplication1.Program::Main][offset 0x
    00000001] Unable to resolve token.
    2 Error(s) Verifying Program.exe
    
    C:\Temp>ver
    
    Microsoft Windows XP [Version 5.1.2600]
    
    class TwoWayRelationship<T1, T2>
    {
        public T2 Get(T1 key) { /* ... */ }
        public T1 Get(T2 key) { /* ... */ }
    }
    
    var r1 = new TwoWayRelationship<int, string>();
    r1.Get(1);
    r1.Get("a");
    
    var r2 = new TwoWayRelationship<int, int>();
    r2.Get(1);  // "The call is ambiguous..."
    
    return test != null ? test : GetDefault();
    
    if (test == null)
        return GetDefault();
    return test;
    
    return test ?? GetDefault();
    
    public class Derived : Base
    {
        public int BrokenAccess()
        {
            return base.m_basePrivateField;
        }
    }
    
    private int m_basePrivateField = 0;
    
    public class Base
    {
        private int m_basePrivateField = 0;
    
        public class Derived : Base
        {
            public int BrokenAccess()
            {
                return base.m_basePrivateField;
            }
        }
    }
    
    public interface MyInterface {
      void Method();
    }
    public class Base {
      public void Method() { }
    }
    public class Derived : Base, MyInterface { }
    
    public class Base
    {
       public virtual void Initialize(dynamic stuff) { 
       //...
       }
    }
    public class Derived:Base
    {
       public override void Initialize(dynamic stuff) {
       base.Initialize(stuff);
       //...
       }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.Remoting.Proxies;
    using System.Reflection;
    using System.Runtime.Remoting.Messaging;
    
    namespace BrokenProxy
    {
        class NotAnIAsyncResult
        {
            public string SomeProperty { get; set; }
        }
    
        class BrokenProxy : RealProxy
        {
            private void HackFlags()
            {
                var flagsField = typeof(RealProxy).GetField("_flags", BindingFlags.NonPublic | BindingFlags.Instance);
                int val = (int)flagsField.GetValue(this);
                val |= 1; // 1 = RemotingProxy, check out System.Runtime.Remoting.Proxies.RealProxyFlags
                flagsField.SetValue(this, val);
            }
    
            public BrokenProxy(Type t)
                : base(t)
            {
                HackFlags();
            }
    
            public override IMessage Invoke(IMessage msg)
            {
                var naiar = new NotAnIAsyncResult();
                naiar.SomeProperty = "o noes";
                return new ReturnMessage(naiar, null, 0, null, (IMethodCallMessage)msg);
            }
        }
    
        interface IRandomInterface
        {
            int DoSomething();
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                BrokenProxy bp = new BrokenProxy(typeof(IRandomInterface));
                var instance = (IRandomInterface)bp.GetTransparentProxy();
                Func<int> doSomethingDelegate = instance.DoSomething;
                IAsyncResult notAnIAsyncResult = doSomethingDelegate.BeginInvoke(null, null);
    
                var interfaces = notAnIAsyncResult.GetType().GetInterfaces();
                Console.WriteLine(!interfaces.Any() ? "No interfaces on notAnIAsyncResult" : "Interfaces");
                Console.WriteLine(notAnIAsyncResult is IAsyncResult); // Should be false, is it?!
                Console.WriteLine(((NotAnIAsyncResult)notAnIAsyncResult).SomeProperty);
                Console.WriteLine(((IAsyncResult)notAnIAsyncResult).IsCompleted); // No way this works.
            }
        }
    }
    
    No interfaces on notAnIAsyncResult
    True
    o noes
    
    Unhandled Exception: System.EntryPointNotFoundException: Entry point was not found.
       at System.IAsyncResult.get_IsCompleted()
       at BrokenProxy.Program.Main(String[] args)