maxp
maxp

Reputation: 25141

Is this possible using generics? c#

I know I can solve the following problem just by creating a custom class, but can the following be strongly typed as a List(or any other type)?

 var x = new object[] 
        { 
            new object[] { new Image(), new TextBox(), new FileUpload() }, 
            new object[] { new Image(), new TextBox() , new FileUpload()} 
        };

The object types in the code above are just for example.

It's the end of the day and my brain has gone abit soft.

Edit: Tuples?

Upvotes: 2

Views: 307

Answers (6)

fljx
fljx

Reputation: 141

Anonymous objects are strongly typed. The only concern is that you can't know the type name (not directly).

Take this example (sorry if it is too long):

        static void T2( )
    {
        var x = new
        {
            a = new { a1 = new Type1( "x.1" ), a2 = new Type2( 1 ), a3 = new Type3( '1' ) },
            b = new { b1 = new Type1( "x.2" ), b2 = new Type2( 2 ), b3 = new Type3( '2' ) }
        };

        var y = new
        {
            a = new { a1 = new Type1( "y.1" ), a2 = new Type2( 1 ), a3 = new Type3( '1' ) },
            b = new { b1 = new Type1( "y.2" ), b2 = new Type2( 2 ), b3 = new Type3( '2' ) }
        };

        var z = new
        {
            a = new { a1 = new Type1( "y.1" ), a2 = new Type3( '1' ) },
            b = new { b1 = new Type3( 'z' ), b2 = new Type2( 2 ) }
        };

        Console.WriteLine( new string( '-', 40 ) );
        Console.WriteLine( "Anonymous object \"x\" is named {0}.", x.GetType( ) );
        Console.WriteLine( "Anonymous object \"y\" is named {0}.", y.GetType( ) );
        Console.WriteLine( "Anonymous object \"z\" is named {0}.", z.GetType( ) );

        Console.WriteLine( new string( '-', 40 ) );
        Console.Write( "Anonymous object \"x\" == \"y\"? " );
        Console.WriteLine( x.Equals( y ) ? "Yes" : "No" );

        Console.Write( "Anonymous object \"x\" == \"z\"? " );
        Console.WriteLine( x.Equals( z ) ? "Yes" : "No" );

        var x2 = new
        {
            a = new { a1 = new Type1( "x.1" ), a2 = new Type2( 1 ), a3 = new Type3( '1' ) },
            b = new { b1 = new Type1( "x.2" ), b2 = new Type2( 2 ), b3 = new Type3( '2' ) }
        };

        Console.Write( "Anonymous object \"x\" == \"x2\"? " );
        Console.WriteLine( x.Equals( x2 ) ? "Yes" : "No" );

        // Uncomment it to give:
        //Error 1   Cannot implicitly convert type 'AnonymousType#1' to 'AnonymousType#2'
#if GiveMeAnError
        z = new
        {
            a = new { a1 = new Type1( "z.1" ), a2 = new Type2( 1 ), a3 = new Type3( '1' ) },
            b = new { b1 = new Type1( "z.2" ), b2 = new Type2( 2 ), b3 = new Type3( '2' ) }
        };

        Console.WriteLine( "Anonymous object \"z\" now is named {0}.", z.GetType( ) );

        Console.Write( "Anonymous object \"x\" == \"z\"? " );
        Console.WriteLine( x.Equals( z ) ? "Yes" : "No" );
#endif
        Console.ReadKey( );
    }

It outputs:

/*----------------------------------------
Anonymous object "x" is named <>f__AnonymousType2`2[<>f__AnonymousType0`3    [anon_obj.Type1,anon_obj.Type2,anon_obj.Type3],<>f__AnonymousType1`3[anon_obj.Type1,anon_obj.Type2,anon_obj.Type3]].
Anonymous object "y" is named <>f__AnonymousType2`2[<>f__AnonymousType0`3[anon_obj.Type1,anon_obj.Type2,anon_obj.Type3],<>f__AnonymousType1`3[anon_obj.Type1,anon_obj.Type2,anon_obj.Type3]].
Anonymous object "z" is named <>f__AnonymousType2`2[<>f__AnonymousType3`2[anon_obj.Type1,anon_obj.Type3],<>f__AnonymousType4`2[anon_obj.Type3,anon_obj.Type2]].
----------------------------------------
Anonymous object "x" == "y"? No
Anonymous object "x" == "z"? No
Anonymous object "x" == "x2"? Yes*/

Each anonymous object composition has its own name and defines an unique type. Objects declared with the same types and type names go to the same type, as in "x == x2".

The original example, though, is tricky, as it defines "object[]" arrays with "object[]" arrays inside. This way

            var x = new object[ ]  
        {  
            new object[] { new Type1("x.1"), new Type2(1), new Type3('1') },  
            new object[] { new Type1("x.2"), new Type2(2) , new Type3('2')}  
        };

        var y = new object[ ]  
        {  
            new object[] { new Type1("y.1"), new Type2(1), new Type3('1') },  
            new object[] { new Type1("y.2"), new Type2(2) , new Type3('2')}  
        };

        var z = new object[ ]  
        {  
            new object[] { new Type1("y.1"), new Type3('1') },  
            new object[] { new Type3('z'), new Type2(2)}  
        };

Will all be the same type (object[]), and the comparison will be allways done by comparing pointers, that will, hopefuly, differ.

        static void T1( )
    {
        var x = new object[ ]  
        {  
            new object[] { new Type1("x.1"), new Type2(1), new Type3('1') },  
            new object[] { new Type1("x.2"), new Type2(2) , new Type3('2')}  
        };

        var y = new object[ ]  
        {  
            new object[] { new Type1("y.1"), new Type2(1), new Type3('1') },  
            new object[] { new Type1("y.2"), new Type2(2) , new Type3('2')}  
        };

        var z = new object[ ]  
        {  
            new object[] { new Type1("y.1"), new Type3('1') },  
            new object[] { new Type3('z'), new Type2(2)}  
        };

        Console.WriteLine( new string( '-', 40 ) );
        Console.WriteLine( "Anonymous object \"x\" is named {0}.", x.GetType( ) );
        Console.WriteLine( "Anonymous object \"y\" is named {0}.", y.GetType( ) );
        Console.WriteLine( "Anonymous object \"z\" is named {0}.", z.GetType( ) );


        Console.WriteLine( new string( '-', 40 ) );
        Console.Write( "Anonymous object \"x\" == \"y\"? " );
        Console.WriteLine( x.Equals( y ) ? "Yes" : "No" );

        Console.Write( "Anonymous object \"x\" == \"z\"? " );
        Console.WriteLine( x.Equals( z ) ? "Yes" : "No" );

        var x2 = new object[ ]  
        {  
            new object[] { new Type1("x.1"), new Type2(1), new Type3('1') },  
            new object[] { new Type1("x.2"), new Type2(2) , new Type3('2')}  
        };

        Console.Write( "Anonymous object \"x\" == \"x2\"? " );
        Console.WriteLine( x.Equals( x2 ) ? "Yes" : "No" );

        z = new object[ ]  
        {  
            new object[] { new Type1("x.1"), new Type2(1), new Type3('1') },  
            new object[] { new Type1("x.2"), new Type2(2) , new Type3('2')}  
        };

        Console.WriteLine( "Anonymous object \"z\" now is named {0}.", z.GetType( ) );


        Console.Write( "Anonymous object \"x\" == \"z\"? " );
        Console.WriteLine( x.Equals( z ) ? "Yes" : "No" );

        Console.Write( "Anonymous object \"x\" == \"z\" (memberwise)? " );
        Console.WriteLine(
            x[ 0 ].Equals( z[ 0 ] )
            && x[ 1 ].Equals( z[ 1 ] )
            ? "Yes" : "No" );

        Console.ReadKey( );
    }

Will output:

/*----------------------------------------
Anonymous object "x" is named System.Object[].
Anonymous object "y" is named System.Object[].
Anonymous object "z" is named System.Object[].
----------------------------------------
Anonymous object "x" == "y"? No
Anonymous object "x" == "z"? No
Anonymous object "x" == "x2"? No
Anonymous object "z" now is named System.Object[].
Anonymous object "x" == "z"? No
Anonymous object "x" == "z" (memberwise)? No
----------------------------------------*/

See the gotcha?

Upvotes: 1

Richard Anthony Hein
Richard Anthony Hein

Reputation: 10650

var x = new []         
{             
    new 
    { 
        Image = new Image(), 
        TextBox = new TextBox(), 
        FileUpload = new FileUpload() 
    },
    new 
    { 
        Image = new Image(), 
        TextBox = new TextBox(), 
        FileUpload = new FileUpload()
    }         
};

Upvotes: 4

Jon Hanna
Jon Hanna

Reputation: 113242

A Tuple<Image, TextBox, FileUpload>[] or perhaps List<Tuple<Image, TextBox, FileUpload>> will do the trick if you are using framework 4.

Otherwise you could use an anonymous type, though it can be awkward beyond that (since you can't declare the type in cases where that is useful).

Finally, it's not the trickiest structure to just roll your own.

Upvotes: 0

Felipe Pessoto
Felipe Pessoto

Reputation: 6969

You can use Tuple as you say. Or anonymous type:

var x = new[] 
    { 
        new { Image = new Image(), TextBox = new TextBox(), FileUpload = new FileUpload() }, 
        new { Image = new Image(), TextBox = new TextBox(), FileUpload = new FileUpload() }
    };

Upvotes: 1

JaredPar
JaredPar

Reputation: 754615

You didn't specify but it looks like you are using the types from System.Web? If so then yes generics can be used to create a more strongly typed collection. For example

List<List<WebControl>> list = new List<List<WebControl>>();
list.Add(new List<WebControl>(new WebControl()[] new Image(), new TextBox(), new FileUpload
() );
list.Add(new List<WebControl>(new WebControl()[] new Image(), new TextBox(), new FileUpload() );

In order to get a very strongly typed collection though you'll need to result to Tuple<> or an anonymous type solution.

Upvotes: 1

Dave Swersky
Dave Swersky

Reputation: 34810

Yep, generic Tuples would work:

http://sankarsan.wordpress.com/2009/11/29/tuple-in-c-4-0/

var myTuples = new List<Tuple<type1, type2, type3>>();

Upvotes: 8

Related Questions