What's the strangest corner case you've se

2018-12-31 08:19发布

I collect a few corner cases and brain teasers and would always like to hear more. The page only really covers C# language bits and bobs, but I also find core .NET things interesting too. For example, here's one which isn't on the page, but which I find incredible:

string x = new string(new char[0]);
string y = new string(new char[0]);
Console.WriteLine(object.ReferenceEquals(x, y));

I'd expect that to print False - after all, "new" (with a reference type) always creates a new object, doesn't it? The specs for both C# and the CLI indicate that it should. Well, not in this particular case. It prints True, and has done on every version of the framework I've tested it with. (I haven't tried it on Mono, admittedly...)

Just to be clear, this is only an example of the kind of thing I'm looking for - I wasn't particularly looking for discussion/explanation of this oddity. (It's not the same as normal string interning; in particular, string interning doesn't normally happen when a constructor is called.) I was really asking for similar odd behaviour.

Any other gems lurking out there?

标签: c# .net
30条回答
柔情千种
2楼-- · 2018-12-31 08:37
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

The output is "Attempted to read protected memory. This is an indication that other memory is corrupt."

查看更多
弹指情弦暗扣
3楼-- · 2018-12-31 08:38

This is the strangest I've encountered by accident:

public class DummyObject
{
    public override string ToString()
    {
        return null;
    }
}

Used as follows:

DummyObject obj = new DummyObject();
Console.WriteLine("The text: " + obj.GetType() + " is " + obj);

Will throw a NullReferenceException. Turns out the multiple additions are compiled by the C# compiler to a call to String.Concat(object[]). Prior to .NET 4, there is a bug in just that overload of Concat where the object is checked for null, but not the result of ToString():

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;

This is a bug by ECMA-334 §14.7.4:

The binary + operator performs string concatenation when one or both operands are of type string. If an operand of string concatenation is null, an empty string is substituted. Otherwise, any non-string operand is converted to its string representation by invoking the virtual ToString method inherited from type object. If ToString returns null, an empty string is substituted.

查看更多
大哥的爱人
4楼-- · 2018-12-31 08:38

Just found a nice little thing today:

public class Base
{
   public virtual void Initialize(dynamic stuff) { 
   //...
   }
}
public class Derived:Base
{
   public override void Initialize(dynamic stuff) {
   base.Initialize(stuff);
   //...
   }
}

This throws compile error.

The call to method 'Initialize' needs to be dynamically dispatched, but cannot be because it is part of a base access expression. Consider casting the dynamic arguments or eliminating the base access.

If I write base.Initialize(stuff as object); it works perfectly, however this seems to be a "magic word" here, since it does exactly the same, everything is still recieved as dynamic...

查看更多
与君花间醉酒
5楼-- · 2018-12-31 08:40

VB.NET, nullables and the ternary operator:

Dim i As Integer? = If(True, Nothing, 5)

This took me some time to debug, since I expected i to contain Nothing.

What does i really contain? 0.

This is surprising but actually "correct" behavior: Nothing in VB.NET is not exactly the same as null in CLR: Nothing can either mean null or default(T) for a value type T, depending on the context. In the above case, If infers Integer as the common type of Nothing and 5, so, in this case, Nothing means 0.

查看更多
查无此人
6楼-- · 2018-12-31 08:42

Assign This!


This is one that I like to ask at parties (which is probably why I don't get invited anymore):

Can you make the following piece of code compile?

    public void Foo()
    {
        this = new Teaser();
    }

An easy cheat could be:

string cheat = @"
    public void Foo()
    {
        this = new Teaser();
    }
";

But the real solution is this:

public struct Teaser
{
    public void Foo()
    {
        this = new Teaser();
    }
}

So it's a little know fact that value types (structs) can reassign their this variable.

查看更多
看风景的人
7楼-- · 2018-12-31 08:42

The scoping in c# is truly bizarre at times. Lets me give you one example:

if (true)
{
   OleDbCommand command = SQLServer.CreateCommand();
}

OleDbCommand command = SQLServer.CreateCommand();

This fails to compile, because command is redeclared? There are some interested guesswork as to why it works that way in this thread on stackoverflow and in my blog.

查看更多
登录 后发表回答