Обощенный тип: ошибка

 
0
 
.NET
ava
V0fka | 23.09.2013, 22: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

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

Подскажите, пожалуйста, что оно хочет?
Comments (6)
ava
diadiavova | 24.09.2013, 00:19 #
Цитата (V0fka @  23.9.2013,  22:42 findReferencedText)
Подскажите, пожалуйста, что оно хочет?

Он хочет знать, что такое Т1... и мне, кстати, тоже интересно smile 
ava
dzaraev | 24.09.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 
ava
V0fka | 24.09.2013, 21:11 #
Цитата (diadiavova @  24.9.2013,  00:19 findReferencedText)
Он хочет знать, что такое Т1... и мне, кстати, тоже интересно 

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

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

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

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

ПС. тему помечаю smile
ava
jsharp36 | 24.09.2013, 22:50 (Edited 24.09.2013 23:58) #
Э... Из кода только догадываться, что произошло. dzaraev верно пишет, но есть еще одна лазейка. Если этот код вырван из какого-то класса уже, то тогда метод "не отклеился". Возможно вы переписали код из книги, который описывал только кусок класса. Тогда возможно и сам класс был обобщенным и уже в описании этого класса есть T1. И все выводы dzaraev-а переносятся на описание параметра в классе, а код, как кусок, не является неправильным.

Но скорее всего, код не верный вообще, т.к. сначала создается пустой класс MainWindow, а потом, судя по имени - обработчик кнопки. Если тот гипотетический внешний класс не является формой да еще обобщенной, то скорее всего, просто когда писали класс MainWindow, неудачно случайно закрыли скобку ))
ava
jsharp36 | 24.09.2013, 23:06 (Edited 25.09.2013 00:13) #
А, нет, сори, Test1 тогда был бы описан внутри этого класса.

Но в общем, идея такая, что не обязательно описывать в методе самом оба обобщенных параметра, а часть может быть описана в классе, в котором этот метод находится. Тогда, тип задается при создании экземпляра. А при вызове метода указывается второй. Тогда не надо столько кода переписывать.
ava
V0fka | 26.09.2013, 20:48 #
jsharp36, спасибо за ответ, сказанное вами прийму к сведению smile
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
advanced
Submit