Generic constraints (Compiler Error CS0309)
От: darklight  
Дата: 22.06.08 14:06
Оценка:
У меня вопрос про
на форуме нашёл только это
Автор: aam
Дата: 13.02.06

Но у меня несколько другой вопрос.
Можно ли перевеси ошибку "Compiler Error CS0309", о несоответсвии генергик-типа заданному ограничению, из ошибки времени компиляции в ошибку времени выполнения.
Т.е., допустим, я во время выполнения сам проверю реальный тип переменных на соответствие нужным ограничениям (оператор is) и в зависимости от реального типа вызову тот или иной метод с параметрами генерик-типов, удовлетворяющих генерик-ограничением этих методов.
Пример

using System;
using System.Collections.Generic;
using System.Text;

namespace WindowsApplication1
{
     public interface Imod
    {
        void mod();
    }

    public class MyClass
    {
        public void func<T>(T a)
        {
            if (a is Imod)
            { f1<T>(a); } //*
            else { f2<T>(a); }
        }

        private void f1<T>(T a) where T : Imod
        {
            a.mod();
        }

        private void f2<T>(T a)
        {
            
        }
    }
}


Строка, помеченная "*" вызывает ошибк времени компиляции

The type 'T' must be convertible to 'WindowsApplication1.Imod' in order to use it as parameter 'T'


Поиск в MSDN Compiler Error CS0309 не дал ответа что с этим делать


Соотвственно один из двух вариантов вопроса:
1. Можно ли как-то конверитровать неограниченный генерик тип в ограниченный для использования в методах требующих ограниченный генерик-тип? Как сделать его "must be convertible"?
2. Как вызывать методы объектов, имеющих, неограниченный генерик тип, зная во время выполнения, конкретный тип? Ни чего кроме варианат использования рефлексии и member.invoke() в голову не приходит — но это не эффективно с точки зрения скорости выполнения (нужна высокая скорость)!


Есл ничего нормальным путём из этого сделать нельзя, то тогда встаёт вопрос о реальной пользы использования generic типо и generic ограничений — если возникает такая проблема при переходе от более обобщённых типов к более ограниченным.

Всего лишь хочу в зависимости от реального типа применять к переменной генерик-типа тот или иной алгоритм (в зависимости от того, оддерживает ли этот тип некоторые методы или не поддерживает) — но получается, что это нормальным путём невозможно
Re: Generic constraints (Compiler Error CS0309)
От: Vovstehn  
Дата: 22.06.08 15:50
Оценка:
Здравствуйте, darklight, Вы писали:

D> skipped


Решение зависит от конкретной ситуации, насколько сильное ограничение и какими методами достигается. Может не совсем понял пример, но в вашем случае же можно обойтись простым приведением:

f1<Imod>((Imod)a);
Re: Generic constraints (Compiler Error CS0309)
От: Mab Россия http://shade.msu.ru/~mab
Дата: 22.06.08 16:48
Оценка:
Здравствуйте, darklight, Вы писали:

D>2. Как вызывать методы объектов, имеющих, неограниченный генерик тип, зная во время выполнения, конкретный тип? Ни чего кроме варианат использования рефлексии и member.invoke() в голову не приходит — но это не эффективно с точки зрения скорости выполнения (нужна высокая скорость)!

Пожалуй, это единственный выход.

D>Есл ничего нормальным путём из этого сделать нельзя, то тогда встаёт вопрос о реальной пользы использования generic типо и generic ограничений — если возникает такая проблема при переходе от более обобщённых типов к более ограниченным.


Не нужно смешивать в одну кучу runtime и compile-time полиморфизм. Их одновременное использование в данном случае легким не будет.
Re: Generic constraints (Compiler Error CS0309)
От: nikov США http://www.linkedin.com/in/nikov
Дата: 22.06.08 18:42
Оценка:
Здравствуйте, darklight, Вы писали:

D>Соотвственно один из двух вариантов вопроса:

D>1. Можно ли как-то конверитровать неограниченный генерик тип в ограниченный для использования в методах требующих ограниченный генерик-тип? Как сделать его "must be convertible"?
К сожалению, это недостаток системы типов .NET.
Обойти это ограничение можно только с помощью рефлекшна.

D>2. Как вызывать методы объектов, имеющих, неограниченный генерик тип, зная во время выполнения, конкретный тип? Ни чего кроме варианат использования рефлексии и member.invoke() в голову не приходит — но это не эффективно с точки зрения скорости выполнения (нужна высокая скорость)!

Можно привести объект к соответствующему интерфейсу, но это вызовет упаковку для value-типов.
Re[2]: Generic constraints (Compiler Error CS0309)
От: darklight  
Дата: 22.06.08 18:59
Оценка:
Здравствуйте, Vovstehn, Вы писали:

V>Здравствуйте, darklight, Вы писали:


D>> skipped


V>Решение зависит от конкретной ситуации, насколько сильное ограничение и какими методами достигается. Может не совсем понял пример, но в вашем случае же можно обойтись простым приведением:


V>
V>f1<Imod>((Imod)a); 
V>


Да! Действительно это работает как же я с разу не догадался спасибо
Re[3]: Generic constraints (Compiler Error CS0309)
От: Mab Россия http://shade.msu.ru/~mab
Дата: 22.06.08 19:01
Оценка:
Здравствуйте, darklight, Вы писали:

V>>
V>>f1<Imod>((Imod)a); 
V>>


D>Да! Действительно это работает как же я с разу не догадался спасибо

Раз этот вариант подходит, то вообще не ясно, зачем было делать этот метод generic. Можно было объявить аргумент как Imod.
Re[2]: Generic constraints (Compiler Error CS0309)
От: darklight  
Дата: 22.06.08 19:13
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, darklight, Вы писали:


D>>Соотвственно один из двух вариантов вопроса:

D>>1. Можно ли как-то конверитровать неограниченный генерик тип в ограниченный для использования в методах требующих ограниченный генерик-тип? Как сделать его "must be convertible"?
N>К сожалению, это недостаток системы типов .NET.
N>Обойти это ограничение можно только с помощью рефлекшна.

D>>2. Как вызывать методы объектов, имеющих, неограниченный генерик тип, зная во время выполнения, конкретный тип? Ни чего кроме варианат использования рефлексии и member.invoke() в голову не приходит — но это не эффективно с точки зрения скорости выполнения (нужна высокая скорость)!

N>Можно привести объект к соответствующему интерфейсу, но это вызовет упаковку для value-типов.

Вот с привидением к определённому интерфейсу у меня и вышла загвозка.
Спасибо Vovstehn полказал как правильно
Упаковка это меньшая из зол, чем рефлексия, и так понятно, что типами-значений не всё так хорошо будет, как хотелось бы, ну у меня как раз ссылочные типы требую отдельной обработки, а типы-значений я пока не планирую обрабатывать в данном алгоритме, значит и упаковки тоже не будет
В общем решение пока найдено — всем спасибо

вот такой вот пример получился — проверил — работает

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
   
    public interface Imod
    {
        void mod();
    }

    public class aClass : Imod
    {
        public void mod()
        {
            throw new System.Exception("mod!");
        }
    }

    public class bClass
    {

    }

    public class MyClass
    {
        public void func<T>(T a)
        {
            if (a is Imod)
            { f1<Imod>((Imod)a); } //*
            else { f2<T>(a); }
        }

        private void f1<T>(T a) where T : Imod
        {
            a.mod();
        }

        private void f2<T>(T a)
        {
            throw new System.Exception("mod unsupported");
        }
    }


    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            aClass a = new aClass();
            bClass b = new bClass();
            MyClass c = new MyClass();
            //c.func<aClass>(a);
            c.func<bClass>(b);
        }
    }
}
Re[4]: Generic constraints (Compiler Error CS0309)
От: darklight  
Дата: 22.06.08 19:17
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>Здравствуйте, darklight, Вы писали:


V>>>
V>>>f1<Imod>((Imod)a); 
V>>>


D>>Да! Действительно это работает как же я с разу не догадался спасибо

Mab>Раз этот вариант подходит, то вообще не ясно, зачем было делать этот метод generic. Можно было объявить аргумент как Imod.

В точку! Простоя запутался в этих генериках и привидениях типа.
Откажусь от генерика в определении метода, оставлю только приведение типа.
Просто исходный аргумент (переменная a) в реальном коде имеет неограниченный генерик-тип
В общем разобрался, спасибо за подсказки!
Re: Generic constraints (Compiler Error CS0309)
От: darklight  
Дата: 22.06.08 19:24
Оценка:
Буквально за 10 минут до того, как я прочитал предложенные решения в ответах на мой вопрос — я сам нашёл своё решение — оно конечно менее изящное, но более унивесральное.
А именно — я сделал вот такую вот функцию

 public System.Object ToObject<T>(T Val) { return Val; }


И всё — на входе генерик-тип — а на выходе уже System.Object — далее с ним можно делать всё-что угодно (в т.ч. приведение типа через оператор as и проверку типа оператором is — но это уже так к слову добавил, может кому (кто ещё сталкнётся с такой же проблемой) так больше понравится...
Re[2]: Generic constraints (Compiler Error CS0309)
От: nikov США http://www.linkedin.com/in/nikov
Дата: 23.06.08 07:21
Оценка: +1
Здравствуйте, darklight, Вы писали:

D>
D> public System.Object ToObject<T>(T Val) { return Val; }
D>


Такое впечатление, что вызов этого метода ничем не будет отличаться от приведения к object.
Re[3]: Generic constraints (Compiler Error CS0309)
От: darklight  
Дата: 23.06.08 18:18
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, darklight, Вы писали:


D>>
D>> public System.Object ToObject<T>(T Val) { return Val; }
D>>


N>Такое впечатление, что вызов этого метода ничем не будет отличаться от приведения к object.


Ага! Только, на мой взгляд, выглядит это более крассиво.
Сравним

T Val = ...;
System.Object o = (System.Object)(Val);
if (o is SomeType) (o as SomeType).DoSomething;


или

T Val = ...;
System.Object o = ToObject(Val);
if (o is SomeType) (o as SomeType).DoSomething;



что наглядней?

Конечно же это дело вкуса

Главное найдено решение из, казалось бы, безвыходной генерик-ситуации
Re[4]: Generic constraints (Compiler Error CS0309)
От: nikov США http://www.linkedin.com/in/nikov
Дата: 23.06.08 18:20
Оценка:
Здравствуйте, darklight, Вы писали:

D>Главное найдено решение из, казалось бы, безвыходной генерик-ситуации


А что делать, если у тебя в констрейнте 2 интерфейса?
Re[4]: Generic constraints (Compiler Error CS0309)
От: romangr Россия  
Дата: 23.06.08 18:29
Оценка:
Здравствуйте, darklight, Вы писали:

T Val = ...;
D>System.Object o = (System.Object)(Val);
D>if (o is SomeType) (o as SomeType).DoSomething;


D>или


D>T Val = ...;
D>System.Object o = ToObject(Val);
D>if (o is SomeType) (o as SomeType).DoSomething;


D>что наглядней?


T Val = ...;
System.Object o = Val;
if (o is SomeType) (o as SomeType).DoSomething;
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Re[5]: Generic constraints (Compiler Error CS0309)
От: darklight  
Дата: 24.06.08 05:20
Оценка:
Здравствуйте, romangr, Вы писали:

R>
R>T Val = ...;
R>System.Object o = Val;
R>if (o is SomeType) (o as SomeType).DoSomething;
R>


ну а так совсем хорошо
но... к сожалению не на всех языках (якобы поддержиающих generic на платформ .NET) это работает. А функция поможет всегда
Re[5]: Generic constraints (Compiler Error CS0309)
От: darklight  
Дата: 24.06.08 05:25
Оценка: -1
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, darklight, Вы писали:


D>>Главное найдено решение из, казалось бы, безвыходной генерик-ситуации


N>А что делать, если у тебя в констрейнте 2 интерфейса?


После приведения к типу System.Object уже не важно сколько там ограничений. И вообще, эти генерик-ограничения это фикция — лучше всё проверять через оператор is во время выполнения (это про generic), т.к. реальный тип известен только вов реям выполнения, а на стадии компиляции неограниченные generic-типы всеьма ограничены в применения без доп. преобразований времени выполнения (аля рассмотренные выше), а ограниченные generic-типы очень ограничены в своём применении вместе с уже разработанными библиотеками (в т.ч. платформенными), т.к. эти ограничения н удастся хорошо сочетать с стандартными типами.
Re[6]: Generic constraints (Compiler Error CS0309)
От: Aen Sidhe Россия Просто блог
Дата: 24.06.08 09:47
Оценка:
Здравствуйте, darklight, Вы писали:

D>Здравствуйте, nikov, Вы писали:


N>>Здравствуйте, darklight, Вы писали:


D>>>Главное найдено решение из, казалось бы, безвыходной генерик-ситуации


N>>А что делать, если у тебя в констрейнте 2 интерфейса?


D>После приведения к типу System.Object уже не важно сколько там ограничений. И вообще, эти генерик-ограничения это фикция — лучше всё проверять через оператор is во время выполнения (это про generic), т.к. реальный тип известен только вов реям выполнения, а на стадии компиляции неограниченные generic-типы всеьма ограничены в применения без доп. преобразований времени выполнения (аля рассмотренные выше), а ограниченные generic-типы очень ограничены в своём применении вместе с уже разработанными библиотеками (в т.ч. платформенными), т.к. эти ограничения н удастся хорошо сочетать с стандартными типами.


Что я не так делаю? Меня вполне устраивают эти ограничения. И даже в случае с операторе есть обходной путь — смотрите BLToolkit
С уважением, Анатолий Попов.
ICQ: 995-908
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.