using extension methods on int - c#

I'm reading about extension methods, and monkeying around with them
to see how they work, and I tried this:
namespace clunk {
public static class oog {
public static int doubleMe(this int x) {
return 2 * x;
}
}
class Program {
static void Main() {
Console.WriteLine(5.doubleMe());
}
}
}
and it worked as expected, successfully extending int with the doubleMe method, printing 10.
Next, being an old C guy, I wondered if I could do this:
namespace clunk {
public static class BoolLikeC {
public static bool operator true(this int i) { return i != 0; }
public static bool operator false(this int i) { return i == 0; }
}
class Program {
static void Main() {
if ( 7 ) {
Console.WriteLine("7 is so true");
}
}
}
}
I would think if the former would work, then the latter ought to work to make it such that
an int used in a boolean context would call the extension method on int, check to see that
7 is not equal to 0, and return true. But instead, the compiler doesn't even like the
later code, and puts the red squiggly lines under the two this's and says "Type expected".
Why shouldn't this work?

Very clever! A nice attempt, but regrettably we did not implement "extension everything", just extension methods.
We considered implementing extension properties, extension operators, extension events, extension constructors, extension interfaces, you name it, but most of them were not compelling enough to make it into C# 4 or the upcoming version of C#. We got as far as designing a syntax for the sort of thing you mention. We got rather farther on extension properties; we almost got extension properties into C# 4 but it ended up not working out. The sad story is here.
http://blogs.msdn.com/b/ericlippert/archive/2009/10/05/why-no-extension-properties.aspx
So, long story short, no such feature, but we'll consider it for hypothetical future releases of the language.
You can of course make a "ToBool()" extension method on int if you really do like the retro C convention that non-zero-means-true.

Extension methods are exactly that—methods.
You cannot make extension operators or properties.
Had that been possible, it would result in very hard-to-read code.
If you aren't familiar with the code base, it's almost impossible to figure out what if (7) means.

As others have said, there's no such thing as extension operators in C#.
The closest you can get, running the risk of facilitating lots of nasty bugs down the line, would be with implicit conversion operators on a custom "bridge" type:
// this works
BoolLikeC evil = 7;
if (evil) Console.WriteLine("7 is so true");
// and this works too
if ((BoolLikeC)7) Console.WriteLine("7 is so true");
// but this still won't work, thankfully
if (7) Console.WriteLine("7 is so true");
// and neither will this
if ((bool)7) Console.WriteLine("7 is so true");
// ...
public struct BoolLikeC
{
private readonly int _value;
public int Value { get { return _value; } }
public BoolLikeC(int value)
{
_value = value;
}
public static implicit operator bool(BoolLikeC x)
{
return (x.Value != 0);
}
public static implicit operator BoolLikeC(int x)
{
return new BoolLikeC(x);
}
}

Unfortunately you cannot introduce new operators, or implement support for existing operators, on types, through extension methods.
Basically, what you want to do cannot be done.
The only way to introduce new operators is to put them in one of the involved types. For binary operators you can put them in your own type, provided your type is one of the two, for unary types you need to put the operator inside the type itself.
Since you can't extend an int in any way, you can't do it.

Console.WriteLine(5.doubleMe());
is equivalent to
Console.WriteLine(oog.doubleMe(5));
Given that, you can see why if ( 7 ) doesn't work.
Extension methods are nothing more than syntax.
As a side note since it is syntax you can call extension methods on null variables because it translates to a normal method call, and methods can take null parameters.

Unfortunately you cannot use extension methods to add operators, and implicit type conversion in C# is implemented as an operator.

In the first instance you are writing an extension method - e.g. extending the functionality of the int data type. In the second code set, you are trying to override the bool operators. These are two totally different things.

Related

C# - interfaces cannot contain operators

Question: Can C# interfaces contain operators?
From searching, the answer I have found is no.
For example, C# interface cannot contain operators
However, in Andrew Troelsen's book "Pro C# 5.0 and the .Net 4.5 framework" he makes the following statement
Alas, operator constraints are not supported under the current version of C#. However, it is possible
(albeit it requires a bit more work) to achieve the desired effect by defining an interface that supports
these operators (C# interfaces can define operators!) and then specifying an interface constraint of the
generic class.
The sentence in bold is what puzzles me. Indeed, when I try the following
using System;
interface MathOps<T> where T : class
{
static T operator+(T a, T b);
}
class MyClass : MathOps<MyClass>
{
int x;
public MyClass(int n = 0)
{
x = n;
}
public static MyClass operator+(MyClass a, MyClass b)
{
return new MyClass(a.x + b.x);
}
}
class Program
{
static void Add<T>(ref T a, ref T b) where T : class, MathOps<T>
{
return a + b;
}
static void Main(string[] args)
{
}
}
The compiler throws the following back at me
error CS0567: Interfaces cannot contain operators
So the case kinda seems settled. But why does Mr Troelsen write the way he does? Am i missing/misinterpreting something?
Thanks.
One key to remember is that, as far as I know, it's not so much that an interface cannot define operators (though that is true) but that interfaces cannot define statics, which is frustrating but also logical.

Generic class with overridden method - which gets called?

I have a class that overrides the addition operator twice. One that takes the type parameter and one that takes a double:
public class A<T>
{
public A() { }
public static A<T> operator +(A<T> a, T t)
{
Console.WriteLine("Generic add called.");
return new A<T>(); // return to keep the compiler happy
}
public static A<T> operator +(A<T> a, double d)
{
Console.WriteLine("Double add called.");
return new A<T>(); // return to keep the compiler happy
}
}
When the class is parameterized by the int type, it behaves as expected:
A<int> aInt = new A<int>();
var test = aInt + 3;
// -> Generic add called.
test = aInt + 3.0;
// -> Double add called.
But when parameterized by the double type, the non-generic add is called:
A<double> aDouble = new A<double>();
var otherTest = aDouble + 3.0;
// -> Double add called.
Assuming this behavior is the norm, I know which will be called. The non-generic override will be preferred. That said...
Will the non-generic method be always be preferred in the event of a collision?
All of the above code is available, runnable in your browser, here
EDIT: This question is related, but it's asking about generic methods, not classes. He gives this code:
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
which does not apply to my usage examples. Distinguishing between a.MyMethod(3) and a.MyMethod<int>(3) is obvious - one is generic and one is not.
The more specific method will be chosen, but that construction is a bad idea because it is technically unspecified behaviour.
To quote #EricLippert, substituting the code snippets for the ones from my question:
But the situation with [aDouble + 3.0] is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type [A<double>]. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.
Are there any examples of this sort of type construction causing truly implementation-defined behaviour?
Yes. See these articles for details:
http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
http://blogs.msdn.com/b/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
Simple answering yes. The compiler assume that because you have treated by hand a particular type parameter, that means that it has some special logic for you. That's why the second operator is called. To say further, operators are nothing more than static methods that accepts some parameters. For your case it's a binary operator so the static method has two parameters.

How to call an extension method from own class without casting?

I'm trying to call an extension method on my own class, but it fails to compile. Consider the following lines of code:
public interface IHelloWorld
{
}
public static class Extensions
{
public static string HelloWorld(this IHelloWorld ext)
{
return "Hello world!";
}
}
public class Test : IHelloWorld
{
public string SaySomething()
{
return HelloWorld();
}
}
Basically I'm extending on the interface. I keep getting this error:
The name 'HelloWorld' does not exist in the current context
Can anybody explains this to me? When I do a cast all seems well:
return ((Test)this).HelloWorld();
Any explanations?
The cast isn't necessary - the this part is. So this works fine:
return this.HelloWorld();
Section 7.6.5.2 explicitly talks about method invocations of the form
expr.identifier ( )
expr.identifier ( args )
expr.identifier < typeargs > ( )
expr.identifier < typeargs > ( args )
This invocation:
HelloWorld()
isn't of that form, as there's no expression involved.
It's not immediately clear to me why the language was designed that way (i.e. why the "implicit this" was excluded) and maybe Eric Lippert will add an answer to that effect later. (The answer may well be along the lines of "because it would have taken a long time to spec, implement and test, for relatively little benefit.") However, this answer at least shows that the C# compiler is sticking to the spec...
this.HelloWorld(); works with no casting.
Remember how Extension methods work:
You use an object and compiler would know the type then it could resolve it to the extension method. If no object is used, then it would not be able to resolve it.
Not really an answer, but too long to fit in the comment section...
Let's take the following example, that I think is pretty common:
public class DoubleSet : List<double>
{
public IEnumerable<double> Square()
{
return this.Select( x => x*x );
}
}
It is a perfectly valid point that the this is not necessary for the compiler to interpret the Select method properly.
However I think that in some ways, imposing the dot notation highlights the fact that we're dealing with an extension method, and that as such, the extension method will only access the members of the current instance through public accessors, even if you're calling it within the private scope of the class.
It makes explicit to the code reader that the extension method will treat the "this" instance as if it didn't know anything of its internal state. And indeed the class of the object is completely unknown to the extension method (as the extension method only knows the interface)
If the code was only:
public IEnumerable<double> Square()
{
return Select( x => x*x );
}
it would be much less obvious that you're dealing with IEnumerable.Select that is actually calling the IList.GetEnumerator and getting every element one by one to call the x => x*x function.

Implicit/Explicit conversion with respect to the "as" keyword

I'm trying to do some unit testing on a project that unfortunately has high level of unit interdependence. Currently, a lot of our classes look to a custom UserIdentity object to determine authentication, but that object has a lot of internal hoop-jumping that I would just as soon avoid when trying to test individual unit functionality.
To work around some of this, I'm trying to create a "mock" version of this UserIdentity that can be plugged in with a more tightly-controlled variable environment.
Long story short, we have a UserIdentity class with several public read-only properties and a static CurrentIdentity (IIdentity) placeholder. I'm able work around just about everything with a "mock" IIdentity implementation, but I'm running into a wall when I reach a point where the CurrentIdentity is cast as a UserIdentity.
It's a pretty straight-forward method:
internal static UserIdentity GetCurrentIdentity()
{
UserIdentity currentIdentity = ApplicationContext.User.Identity as UserIdentity;
return currentIdentity;
}
I've set up my mock object to create a member of the UserIdentity type, and then do something like this:
public static implicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
or this
public static explicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
The problem is that as far as I can tell, that 'as' doesn't seem to invoke either an implicit or explicit conversion operation on my mock object. My question(s) is(are?), am I missing something simple here or will this not work because (I'm guessing) the 'as' operation looks directly to class inheritance (which my object does not do...)?
Also, a bit off topic maybe, but why can there not be simultaneous explicit and implicit operators of the same resultant type within a class? Unless I'm missing something silly, the compiler balks if I try to have both conversion operators at once. I have to pick one or the other.
UPDATE
Okay, now I'm thoroughly confused. Maybe I'm getting sloppy, but I've tried doing the direct cast, and I can't seem to get that to work either. I read up on the operator at MSDN, and the example shows the operator going in the resultant class rather than the source class, but I'm not sure if that matters or not (I tried both places in the code below). Either way, I tried to set up a simple test bed to see what I might be doing wrong, but I can't get that to work either...Here's what I've got
class Program
{
// Shared Interface
public interface IIdentity { }
// "real" class (not conducive to inheritence)
public class CoreIdentity : IIdentity
{
internal CoreIdentity() { }
// Just in case (if this has to be here, that seems unfortunate)
public static explicit operator CoreIdentity(ExtendedIdentity src)
{
return src.Identity;
}
}
// "mock" class (Wraps core object)
public class ExtendedIdentity : IIdentity
{
public CoreIdentity Identity { get; set; }
public ExtendedIdentity()
{
Identity = new CoreIdentity();
}
// This is where the operator seems like it should belong...
public static explicit operator CoreIdentity(ExtendedIdentity src)
{
return src.Identity;
}
}
// Dummy class to obtain "current core identity"
public class Foo
{
public IIdentity Identity { get; set; }
public CoreIdentity GetCoreIdentity()
{
return (CoreIdentity)Identity;
}
}
static void Main(string[] args)
{
ExtendedIdentity identity = new ExtendedIdentity();
Foo foo = new Foo();
foo.Identity = identity;
CoreIdentity core = foo.GetCoreIdentity();
}
}
But that throws the following exception when I invoke foo.GetCoreIdentity():
Unable to cast object of type 'ExtendedIdentity' to type 'CoreIdentity'.
and I can't catch either of my explicit operators with a break point, so it looks like it's making this determination without even "trying" the conversion routes I've provided.
Surely I'm missing something obvious. Does the fact that I have my Identity (in Foo) defined as IIdentity somehow prevent resolution of the cast using the explicit operators of the implementing type? That would strike me as odd.
UPDATE (#2)
I feel like I'm spamming my post with all these updates (maybe I should get my act together before being so trigger-happy :) ) Anyway, I modified my Foo's GetCoreIdentityMethod to do this instead:
public CoreIdentity GetCoreIdentity()
{
ExtendedIdentity exId = Identity as ExtendedIdentity;
if (exId != null)
return (CoreIdentity)exId;
return (CoreIdentity)Identity;
}
and (after having to clean up the ambiguous reference caused by having the operator in both classes), it did step into my explicit conversion operator code, and it did work as expected. So I guess it looks like the explicit operators are not resolved polymorphically (is that the correct understanding?), and the fact that my property was typed as an IIdentity rather than an ExtendedIdentity prevented it from invoking the cast logic even though it was of the ExtendedIdentity type at the time it was invoked. That strikes me as very peculiar and unexpected....and kind of unfortunate.
I don't want to have to re-write the keeper of the CurrentIdentity object to make it aware of my special test cast mocks. I wanted to encapsulate that "special" logic into the mock itself, so this really throws me for a loop.
Does the fact that I have my Identity
(in Foo) defined as IIdentity somehow
prevent resolution of the cast using
the explicit operators of the
implementing type?
Here's a hint: how do you define an explicit (or implicit, for that matter) conversion operator? (I know you know this since you already did it; I am asking the question to illustrate a point.)
public static explicit operator UserIdentity(MockUserIdentity src)
{
return src.UserIdentity;
}
There's something very important to realize here. The C# designers made the wise choice of making all operators static. So the explicit operator defined above translates to essentially a static method call looking something like this:
public static UserIdentity op_Explicit(MockUserIdentity src)
{
return src.UserIdentity;
}
Now, here is what I'm getting at. The behavior that perplexed you in your question because it seemed to fail in the polymorphism department was really the result of C#'s system of method overload resolution.
If I have two methods:
void Write(string s) { Console.WriteLine("string"); }
void Write(object o) { Console.WriteLine("object"); }
...and then I have this program:
object x = "Hello!";
Write(x);
What will the output be?
The answer is "object" because the Write(object) overload was selected by the compiler -- as well it should have been. Write is not an instance method to be overridden by some derived type according to normal polymorphism; it is a static method, with overloads between which the compiler must make a choice. Since x in the above code is declared to be of type object, that choice is unambiguously Write(object).
So in the case of your code, where you have this:
public IIdentity Identity { get; set; }
public CoreIdentity GetCoreIdentity()
{
return (CoreIdentity)Identity;
}
The compiler must investigate: is there an op_Explicit overload which accepts an IIdentity parameter? No, there is not. There's one that accepts a UserIdentity parameter, but that's too specific (just as Write(string) was too specific for x in the example above).
So the reason your explicit operator was not called in your initial tests was that the compiler will not resolve (CoreIdentity)Identity to that particular overload. This is also why your modified version does work:
public CoreIdentity GetCoreIdentity()
{
ExtendedIdentity exId = Identity as ExtendedIdentity;
if (exId != null)
{
// Since exId is actually declared to be of type ExtendedIdentity,
// the compiler can choose the operator overload accepting
// an ExtendedIdentity parameter -- so this will work.
return (CoreIdentity)exId;
}
return (CoreIdentity)Identity;
}
as does not invoke conversion operators. See: http://msdn.microsoft.com/en-us/library/cscsdfbt(v=VS.100).aspx
Use a (cast).
So, why don't you use an explicit cast?
// will throw if cast fails
internal static UserIdentity GetCurrentIdentity()
{
UserIdentity currentIdentity = (UserIdentity) ApplicationContext.User.Identity ;
return currentIdentity;
}
This ought to trigger your explicit operator. You can test with is first to make it safer.
As mentioned by Ray as doesn't invoke the conversion operators.
That said, you should be using an explicit cast in that type of scenarios.
That way, You get very clear information when something isn't set up right and the object at ApplicationContext.User.Identity wasn't what the code expected it to.

What's the strangest corner case you've seen in C# or .NET? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
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?
I think I showed you this one before, but I like the fun here - this took some debugging to track down! (the original code was obviously more complex and subtle...)
static void Foo<T>() where T : new()
{
T t = new T();
Console.WriteLine(t.ToString()); // works fine
Console.WriteLine(t.GetHashCode()); // works fine
Console.WriteLine(t.Equals(t)); // works fine
// so it looks like an object and smells like an object...
// but this throws a NullReferenceException...
Console.WriteLine(t.GetType());
}
So what was T...
Answer: any Nullable<T> - such as int?. All the methods are overridden, except GetType() which can't be; so it is cast (boxed) to object (and hence to null) to call object.GetType()... which calls on null ;-p
Update: the plot thickens... Ayende Rahien threw down a similar challenge on his blog, but with a where T : class, new():
private static void Main() {
CanThisHappen<MyFunnyType>();
}
public static void CanThisHappen<T>() where T : class, new() {
var instance = new T(); // new() on a ref-type; should be non-null, then
Debug.Assert(instance != null, "How did we break the CLR?");
}
But it can be defeated! Using the same indirection used by things like remoting; warning - the following is pure evil:
class MyFunnyProxyAttribute : ProxyAttribute {
public override MarshalByRefObject CreateInstance(Type serverType) {
return null;
}
}
[MyFunnyProxy]
class MyFunnyType : ContextBoundObject { }
With this in place, the new() call is redirected to the proxy (MyFunnyProxyAttribute), which returns null. Now go and wash your eyes!
Bankers' Rounding.
This one is not so much a compiler bug or malfunction, but certainly a strange corner case...
The .Net Framework employs a scheme or rounding known as Banker's Rounding.
In Bankers' Rounding the 0.5 numbers are rounded to the nearest even number, so
Math.Round(-0.5) == 0
Math.Round(0.5) == 0
Math.Round(1.5) == 2
Math.Round(2.5) == 2
etc...
This can lead to some unexpected bugs in financial calculations based on the more well known Round-Half-Up rounding.
This is also true of Visual Basic.
What will this function do if called as Rec(0) (not under the debugger)?
static void Rec(int i)
{
Console.WriteLine(i);
if (i < int.MaxValue)
{
Rec(i + 1);
}
}
Answer:
On 32-bit JIT it should result in a StackOverflowException
On 64-bit JIT it should print all the numbers to int.MaxValue
This is because the 64-bit JIT compiler applies tail call optimisation, whereas the 32-bit JIT does not.
Unfortunately I haven't got a 64-bit machine to hand to verify this, but the method does meet all the conditions for tail-call optimisation. If anybody does have one I'd be interested to see if it's true.
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.
Few years ago, when working on loyality program, we had an issue with the amount of points given to customers. The issue was related to casting/converting double to int.
In code below:
double d = 13.6;
int i1 = Convert.ToInt32(d);
int i2 = (int)d;
does i1 == i2 ?
It turns out that i1 != i2.
Because of different rounding policies in Convert and cast operator the actual values are:
i1 == 14
i2 == 13
It's always better to call Math.Ceiling() or Math.Floor() (or Math.Round with MidpointRounding that meets our requirements)
int i1 = Convert.ToInt32( Math.Ceiling(d) );
int i2 = (int) Math.Ceiling(d);
They should have made 0 an integer even when there's an enum function overload.
I knew C# core team rationale for mapping 0 to enum, but still, it is not as orthogonal as it should be. Example from Npgsql.
Test example:
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");
}
}
}
This is one of the most unusual i've seen so far (aside from the ones here of course!):
public class Turtle<T> where T : Turtle<T>
{
}
It lets you declare it but has no real use, since it will always ask you to wrap whatever class you stuff in the center with another Turtle.
[joke] I guess it's turtles all the way down... [/joke]
Here's one I only found out about recently...
interface IFoo
{
string Message {get;}
}
...
IFoo obj = new IFoo("abc");
Console.WriteLine(obj.Message);
The above looks crazy at first glance, but is actually legal.No, really (although I've missed out a key part, but it isn't anything hacky like "add a class called IFoo" or "add a using alias to point IFoo at a class").
See if you can figure out why, then: Who says you can’t instantiate an interface?
When is a Boolean neither True nor False?
Bill discovered that you can hack a boolean so that if A is True and B is True, (A and B) is False.
Hacked Booleans
I'm arriving a bit late to the party, but I've got three four five:
If you poll InvokeRequired on a control that hasn't been loaded/shown, it will say false - and blow up in your face if you try to change it from another thread (the solution is to reference this.Handle in the creator of the control).
Another one which tripped me up is that given an assembly with:
enum MyEnum
{
Red,
Blue,
}
if you calculate MyEnum.Red.ToString() in another assembly, and in between times someone has recompiled your enum to:
enum MyEnum
{
Black,
Red,
Blue,
}
at runtime, you will get "Black".
I had a shared assembly with some handy constants in. My predecessor had left a load of ugly-looking get-only properties, I thought I'd get rid of the clutter and just use public const. I was more than a little surprised when VS compiled them to their values, and not references.
If you implement a new method of an interface from another assembly, but you rebuild referencing the old version of that assembly, you get a TypeLoadException (no implementation of 'NewMethod'), even though you have implemented it (see here).
Dictionary<,>: "The order in which the items are returned is undefined". This is horrible, because it can bite you sometimes, but work others, and if you've just blindly assumed that Dictionary is going to play nice ("why shouldn't it? I thought, List does"), you really have to have your nose in it before you finally start to question your assumption.
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.
I found a second really strange corner case that beats my first one by a long shot.
String.Equals Method (String, String, StringComparison) is not actually side effect free.
I was working on a block of code that had this on a line by itself at the top of some function:
stringvariable1.Equals(stringvariable2, StringComparison.InvariantCultureIgnoreCase);
Removing that line lead to a stack overflow somewhere else in the program.
The code turned out to be installing a handler for what was in essence a BeforeAssemblyLoad event and trying to do
if (assemblyfilename.EndsWith("someparticular.dll", StringComparison.InvariantCultureIgnoreCase))
{
assemblyfilename = "someparticular_modified.dll";
}
By now I shouldn't have to tell you. Using a culture that hasn't been used before in a string comparison causes an assembly load. InvariantCulture is not an exception to this.
Here is an example of how you can create a struct that causes the error message "Attempted to read or write protected memory. This is often an indication that other memory is corrupt".
The difference between success and failure is very subtle.
The following unit test demonstrates the problem.
See if you can work out what went wrong.
[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);
}
}
C# supports conversions between arrays and lists as long as the arrays are not multidimensional and there is an inheritance relation between the types and the types are reference types
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" };
Note that this does not work:
object[] oArray2 = new int[] { 1, 2, 3 }; // Error: Cannot implicitly convert type 'int[]' to 'object[]'
int[] iArray = (int[])oArray2; // Error: Cannot convert type 'object[]' to 'int[]'
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.
Interesting - when I first looked at that I assumed it was something the C# compiler was checking for, but even if you emit the IL directly to remove any chance of interference it still happens, which means it really is the newobj op-code that's doing the checking.
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);
It also equates to true if you check against string.Empty which means this op-code must have special behaviour to intern empty strings.
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."
PropertyInfo.SetValue() can assign ints to enums, ints to nullable ints, enums to nullable enums, but not ints to nullable enums.
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 !!!
Full description here
What if you have a generic class that has methods that could be made ambiguous depending on the type arguments? I ran into this situation recently writing a two-way dictionary. I wanted to write symmetric Get() methods that would return the opposite of whatever argument was passed. Something like this:
class TwoWayRelationship<T1, T2>
{
public T2 Get(T1 key) { /* ... */ }
public T1 Get(T2 key) { /* ... */ }
}
All is well good if you make an instance where T1 and T2 are different types:
var r1 = new TwoWayRelationship<int, string>();
r1.Get(1);
r1.Get("a");
But if T1 and T2 are the same (and probably if one was a subclass of another), it's a compiler error:
var r2 = new TwoWayRelationship<int, int>();
r2.Get(1); // "The call is ambiguous..."
Interestingly, all other methods in the second case are still usable; it's only calls to the now-ambiguous method that causes a compiler error. Interesting case, if a little unlikely and obscure.
C# Accessibility Puzzler
The following derived class is accessing a private field from its base class, and the compiler silently looks to the other side:
public class Derived : Base
{
public int BrokenAccess()
{
return base.m_basePrivateField;
}
}
The field is indeed private:
private int m_basePrivateField = 0;
Care to guess how we can make such code compile?
.
.
.
.
.
.
.
Answer
The trick is to declare Derived as an inner class of Base:
public class Base
{
private int m_basePrivateField = 0;
public class Derived : Base
{
public int BrokenAccess()
{
return base.m_basePrivateField;
}
}
}
Inner classes are given full access to the outer class members. In this case the inner class also happens to derive from the outer class. This allows us to "break" the encapsulation of private members.
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...
In an API we're using, methods that return a domain object might return a special "null object". In the implementation of this, the comparison operator and the Equals() method are overridden to return true if it is compared with null.
So a user of this API might have some code like this:
return test != null ? test : GetDefault();
or perhaps a bit more verbose, like this:
if (test == null)
return GetDefault();
return test;
where GetDefault() is a method returning some default value that we want to use instead of null. The surprise hit me when I was using ReSharper and following it's recommendation to rewrite either of this to the following:
return test ?? GetDefault();
If the test object is a null object returned from the API instead of a proper null, the behavior of the code has now changed, as the null coalescing operator actually checks for null, not running operator= or Equals().
Consider this weird case:
public interface MyInterface {
void Method();
}
public class Base {
public void Method() { }
}
public class Derived : Base, MyInterface { }
If Base and Derived are declared in the same assembly, the compiler will make Base::Method virtual and sealed (in the CIL), even though Base doesn't implement the interface.
If Base and Derived are in different assemblies, when compiling the Derived assembly, the compiler won't change the other assembly, so it will introduce a member in Derived that will be an explicit implementation for MyInterface::Method that will just delegate the call to Base::Method.
The compiler has to do this in order to support polymorphic dispatch with regards to the interface, i.e. it has to make that method virtual.
The following might be general knowledge I was just simply lacking, but eh. Some time ago, we had a bug case which included virtual properties. Abstracting the context a bit, consider the following code, and apply breakpoint to specified area :
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 { } }
}
While in the Derived object context, you can get the same behavior when adding base.Property as a watch, or typing base.Property into the quickwatch.
Took me some time to realize what was going on. In the end I was enlightened by the Quickwatch. When going into the Quickwatch and exploring the Derived object d (or from the object's context, this) and selecting the field base, the edit field on top of the Quickwatch displays the following cast:
((TestProject1.Base)(d))
Which means that if base is replaced as such, the call would be
public string BaseProperty { get { return ((TestProject1.Base)(d)).Property; } private set { } }
for the Watches, Quickwatch and the debugging mouse-over tooltips, and it would then make sense for it to display "AWESOME" instead of "BASE_AWESOME" when considering polymorphism. I'm still unsure why it would transform it into a cast, one hypothesis is that call might not be available from those modules' context, and only callvirt.
Anyhow, that obviously doesn't alter anything in terms of functionality, Derived.BaseProperty will still really return "BASE_AWESOME", and thus this was not the root of our bug at work, simply a confusing component. I did however find it interesting how it could mislead developpers which would be unaware of that fact during their debug sessions, specially if Base is not exposed in your project but rather referenced as a 3rd party DLL, resulting in Devs just saying :
"Oi, wait..what ? omg that DLL is
like, ..doing something funny"
This one's pretty hard to top. I ran into it while I was trying to build a RealProxy implementation that truly supports Begin/EndInvoke (thanks MS for making this impossible to do without horrible hacks). This example is basically a bug in the CLR, the unmanaged code path for BeginInvoke doesn't validate that the return message from RealProxy.PrivateInvoke (and my Invoke override) is returning an instance of an IAsyncResult. Once it's returned, the CLR gets incredibly confused and loses any idea of whats going on, as demonstrated by the tests at the bottom.
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.
}
}
}
Output:
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)
I'm not sure if you'd say this is a Windows Vista/7 oddity or a .Net oddity but it had me scratching my head for a while.
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."
In Windows Vista/7 the file will actually be written to C:\Users\<username>\Virtual Store\Program Files\my folder\test.txt
Have you ever thought the C# compiler could generate invalid CIL? Run this and you'll get a TypeLoadException:
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));
}
}
I don't know how it fares in the C# 4.0 compiler though.
EDIT: this is the output from my system:
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]
There is something really exciting about C#, the way it handles closures.
Instead of copying the stack variable values to the closure free variable, it does that preprocessor magic wrapping all occurences of the variable into an object and thus moves it out of stack - straight to the heap! :)
I guess, that makes C# even more functionally-complete (or lambda-complete huh)) language than ML itself (which uses stack value copying AFAIK). F# has that feature too, as C# does.
That does bring much delight to me, thank you MS guys!
It's not an oddity or corner case though... but something really unexpected from a stack-based VM language :)
From a question I asked not long ago:
Conditional operator cannot cast implicitly?
Given:
Bool aBoolValue;
Where aBoolValue is assigned either True or False;
The following will not compile:
Byte aByteValue = aBoolValue ? 1 : 0;
But this would:
Int anIntValue = aBoolValue ? 1 : 0;
The answer provided is pretty good too.
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.

Categories

Resources