Возможно ли это с помощью дженериков?C # - PullRequest
2 голосов
/ 04 октября 2010

Я знаю, что могу решить следующую проблему, просто создав собственный класс, но можно ли строго указать тип List (или любой другой тип)?

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

Типы объектов вприведенный выше код приведен только для примера.

Конец дня, и мой мозг успокоился.

Редактировать: Кортежи?

Ответы [ 6 ]

8 голосов
/ 04 октября 2010

Да, универсальные кортежи будут работать:

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

var myTuples = new List<Tuple<type1, type2, type3>>();
4 голосов
/ 04 октября 2010
var x = new []         
{             
    new 
    { 
        Image = new Image(), 
        TextBox = new TextBox(), 
        FileUpload = new FileUpload() 
    },
    new 
    { 
        Image = new Image(), 
        TextBox = new TextBox(), 
        FileUpload = new FileUpload()
    }         
};
1 голос
/ 04 октября 2010

Анонимные объекты строго типизированы . Единственная проблема заключается в том, что вы не можете знать имя типа (не напрямую).

Возьмите этот пример (извините, если он слишком длинный):

        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( );
    }

Это выводит:

/*----------------------------------------
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*/

Каждый состав анонимного объекта имеет собственное имя и определяет уникальный тип. Объекты, объявленные с теми же типами и именами типов, относятся к тому же типу, что и в «x == x2».

Оригинальный пример, однако, хитрый, поскольку он определяет массивы "object []" с массивами "object []" внутри. Сюда

            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)}  
        };

Все они будут одного и того же типа (объект []), и сравнение будет всегда выполняться путем сравнения указателей , которые, надеюсь, будут отличаться.

        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( );
    }

Будет выводить:

/*----------------------------------------
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
----------------------------------------*/

Видишь гочу?

1 голос
/ 04 октября 2010

Вы можете использовать Tuple, как вы говорите. Или анонимный тип:

var x = new[] 
    { 
        new { Image = new Image(), TextBox = new TextBox(), FileUpload = new FileUpload() }, 
        new { Image = new Image(), TextBox = new TextBox(), FileUpload = new FileUpload() }
    };
1 голос
/ 04 октября 2010

Вы не указали, но похоже, что вы используете типы из System.Web? Если это так, то да можно использовать дженерики для создания более строго типизированной коллекции. Например

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() );

Чтобы получить очень строго типизированную коллекцию, вам нужно получить Tuple<> или решение анонимного типа.

0 голосов
/ 04 октября 2010

A Tuple<Image, TextBox, FileUpload>[] или, возможно, List<Tuple<Image, TextBox, FileUpload>> добьются цели, если вы используете framework 4.

В противном случае вы можете использовать анонимный тип, хотя это может быть неловко (поскольку вы не можете объявить тип в тех случаях, когда это полезно).

Наконец, это не самая хитрая структура, чтобы просто свернуть свою собственную.

...