Skip to content

Instantly share code, notes, and snippets.

@VladimirReshetnikov
Last active January 2, 2016 23:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VladimirReshetnikov/8380121 to your computer and use it in GitHub Desktop.
Save VladimirReshetnikov/8380121 to your computer and use it in GitHub Desktop.
class Program
{
// What argument do you need to provide to this method so that it returns true?
public static bool AreYouNuts<T>(T[] array)
{
if (array == null || array.Length == 0)
return false;
var local = (T[]) array.Clone();
var x = local[0];
var y = local.GetValue(0);
return x.GetType() != y.GetType();
}
}
@NikGovorov
Copy link

Uses reflection and behaviour that you've recently described.

using System;
using System.Diagnostics;
using System.Reflection;

namespace VladimirReshetnikovsQuiz
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var allocate = typeof (RuntimeTypeHandle).GetMethod("Allocate", (BindingFlags) 40);

            var instanceOfOpenType = allocate.Invoke(null, new object[] {typeof (Base<>.NestedEnum)});

            var method = typeof (Program).GetMethod("AreYouNuts");
            var genericMethod = method.MakeGenericMethod(typeof (Base<int>.NestedEnum));


            Console.WriteLine(genericMethod.Invoke(null, new object[] {new[] {(Derived.NestedEnum) instanceOfOpenType}}));
            Console.ReadLine();
        }

        public static bool AreYouNuts<T>(T[] array)
        {
            if (array == null || array.Length == 0)
                return false;

            var local = (T[]) array.Clone();

            T x = local[0];
            object y = local.GetValue(0);

            return x.GetType() != y.GetType();
        }
    }

    internal class Base<T>
    {
        public enum NestedEnum
        {
        }
    }

    internal class Derived : Base<int>
    {
        public new enum NestedEnum
        {
        }
    }
}

@VladimirReshetnikov
Copy link
Author

This is a huge overkill. It can be done in one line, without any reflection, enums or generic types.

@NikGovorov
Copy link

Hmm interesting, I'll spend more time tonight on this.

@mburnell
Copy link

Console.WriteLine(AreYouNuts((int[])(object) new uint[1]));

@leppie
Copy link

leppie commented Jan 13, 2014

@mburnell: nice! I went down that signed/unsigned route, but could not get it working...

@VladimirReshetnikov
Copy link
Author

@mburnell Yes! This is what I had in mind. One can do this using enums, too.

@leppie
Copy link

leppie commented Jan 13, 2014

@VladimirReshetnikov
Works for (UIntPtr[])(object)new IntPtr[1] { new IntPtr(0) }) too.
I thought it might be something to do with an implicit conversion from 0 but neither of those allow it (directly).
Perhaps something to do with primitive CLR types that is convertible from 0?
But why does bool not work then with (byte[])(object)new bool[1] ?

@airbreather
Copy link

@VladimirReshetnikov
Loving these puzzles.

@leppie
As Vladimir pointed out, it works with enums too, so it doesn't have to be a primitive CLR type, unless you don't count those :-)

enum E { }
private static void Main()
{
    Console.WriteLine(AreYouNuts((int[])(Array)new E[1]));
}

This quirk has actually burned me before. Used the pattern here http://stackoverflow.com/a/5418187/1083771 to convert an sbyte[] to byte[] and then trying to stuff that array into an ADO.Net DataRow field of type byte[]. The array's underlying type is still sbyte[], even though you can treat it like a byte[].

@VladimirReshetnikov
Copy link
Author

It is a CLR rule. See Ecma-335, Partition I, 8.7.1 Assignment compatibility for signature types:
...
7. T is a zero-based rank-1 array V[], and U is IList, and V is array-element-compatible-with W.
...
[Note: in other words, array-element-compatible-with extends compatible-with but is agnostic
with respect to enumerations and integral signed-ness. end note]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment