Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Обощенный тип: ошибка


Автор: V0fka 23.9.2013, 21:42
Привет!

В одной книге был примерчик. Для меня был не совсем понятен, я решил поковыряться с ним. В общем есть такой код:

Код

   public class Test1
    {
        public int Prop
        {
            get;
            set;
        }
    }

    public class Test2
    {
        public int Prop
        {
            get;
            set;
        }
    }

public partial class MainWindow : Window
    {
    }

private List<T1> TestGeneric<T2>(T2 param) where T2 : Test2
        {
            List<T1> l = new List<T1>();
            
            T1 t1 = (T1)new Test1();
            t1.Prop = param.Prop;
            l.Add(t1);

            return l;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            List<Test1> l;
            Test2 t2 = new Test2();
            t2.Prop = 3;
            l = TestGeneric<Test2>(t2);
        }


И на строке private List<T1> TestGeneric<T2>(T2 param) where T2 : Test2 студия ругается "Не удалось найти имя типа или пространства имен "Т1" (пропущена директива using или ссылка на сборку?)".

Пример притянутый за уши, интересно разобраться именно с таким случаем. Если сделать, чтобы в методе TestGeneric все обобщенные типы были одинаковые, т.е., например, так:
Код

private List<T2> TestGeneric<T2>(T2 param) where T2 : Test2

то ошибки нету. Но я хочу именно так, как написал: тип возвращаемого значения один, а тип входного параметра другой.

Подскажите, пожалуйста, что оно хочет?

Автор: diadiavova 24.9.2013, 00:19
Цитата(V0fka @  23.9.2013,  22:42 Найти цитируемый пост)
Подскажите, пожалуйста, что оно хочет?

Он хочет знать, что такое Т1... и мне, кстати, тоже интересно smile 

Автор: dzaraev 24.9.2013, 07:09
Во-первых у вас метод отклеился у вас метод объявлен вне класса smile.
Во-вторых, если этот метод должен был быть в классе MainWindow например, то ему необходимо добавить в объявление соответствующий параметр типа. Объявление метода TestGeneric должно выглядеть примерно так:
Код

public partial class MainWindow : Window
    {
         private List<T1> TestGeneric<T1,T2>(T2 param) where T2 : Test2
         {
               //тело метода
         }
    }

Далее, строка 
Код

  T1 t1 = (T1)new Test1();

даже при наличии параметра T1 не будет компилироваться, т.к. у вас не задано ограничение для параметра T1. Добавим его, объявление метода будет теперь выглядеть так:
Код

private List<T1> TestGeneric<T1, T2>(T2 param) 
    where T2 : Test2 
    where T1 : Test1 //добавили ограничение для T1

Если вы хотите внутри тела метода создавать не конкретно Test1, а, например, писать new T1(), то вам необходимо добавить ограничение new(), тогда метод можно переписать вот так:
Код

        private List<T1> TestGeneric<T1, T2>(T2 param) 
            where T2 : Test2 
            where T1 : Test1, new() //добавили ограничение new
        {
            List<T1> l = new List<T1>();

            T1 t1 = new T1(); //теперь можно писать new T1()
            t1.Prop = param.Prop;
            l.Add(t1);
            return l;
        }

Подробнее об ограничениях параметров типа читайте тут: http://msdn.microsoft.com/ru-ru/library/d5x73970.aspx

И последнее:
Код

private void button1_Click(object sender, RoutedEventArgs e)
        {
            List<Test1> l;
            Test2 t2 = new Test2();
            t2.Prop = 3;
            l = TestGeneric<Test2>(t2);
        }        

Этот код у вас тоже не скомпилится, т.к. теперь нам необходимо указывать два аргумента типа для метода TestGeneric, т.е. вы же добавили параметр T1, теперь же добавим и аргумент для него при вызове метода - будет вот так:
Код

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            List<Test1> l;
            Test2 t2 = new Test2();
            t2.Prop = 3;
            l = TestGeneric<Test1, Test2>(t2); //добавили аргумент для T1
        }

Если проблема решена - помечаем  smile 

Автор: V0fka 24.9.2013, 21:11
Цитата(diadiavova @  24.9.2013,  00:19 Найти цитируемый пост)
Он хочет знать, что такое Т1... и мне, кстати, тоже интересно 

Я не знал, что
Цитата(dzaraev @  24.9.2013,  07:09 Найти цитируемый пост)
если этот метод должен был быть в классе MainWindow например, то ему необходимо добавить в объявление соответствующий параметр типа

Думал, что где попало можно написать, компилятор догадается smile

dzaraev, ответ - не просто ответ на заданный вопрос, а и ответ на будущие вопросы, которые бы возникли по этой теме smile . Спасибо большое! smile 

Это получается, что все обобщенные типы должны быть обязательно перечислены возле объявления именно метода/класса?

ПС. тему помечаю smile

Автор: jsharp36 24.9.2013, 22:50
Э... Из кода только догадываться, что произошло. dzaraev верно пишет, но есть еще одна лазейка. Если этот код вырван из какого-то класса уже, то тогда метод "не отклеился". Возможно вы переписали код из книги, который описывал только кусок класса. Тогда возможно и сам класс был обобщенного типа и уже в описании этого класса есть T1. И все выводы dzaraev-а переносятся на описание параметра в классе, а код, как кусок, не является неправильным.

Но скорее всего, код не верный вообще, т.к. сначала создается пустой класс MainWindow, а потом, судя по имени - обработчик кнопки. Если тот гипотетический внешний класс не является формой да еще обобщенной, то скорее всего, просто когда писали класс MainWindow, неудачно случайно закрыли скобку ))

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//Обощенный-тип-ошибка-id52408c2eae2015a372000006#findElement_E7045_5241ed0bae2015ef5b00152d_0

Автор: jsharp36 24.9.2013, 23:06
А, нет, сори, Test2 тогда был бы описан внутри этого класса.

Но в общем, идея такая, что не обязательно описывать в методе самом оба обобщенных параметра, а часть может быть описана в классе, в котором этот метод находится. Тогда, тип задается при создании экземпляра. А при вызове метода указывается второй. Тогда не надо столько кода переписывать.

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//Обощенный-тип-ошибка-id52408c2eae2015a372000006#findElement_E7045_5241f0b3ae2015103a0016c8_0

Автор: V0fka 26.9.2013, 20:48
jsharp36, спасибо за ответ, сказанное вами прийму к сведению smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)