Преобразование типов делегатов
От: AkaSaint  
Дата: 25.04.06 00:09
Оценка:
Здравствуйте. Дело происходит в VS2005 (C#). В некотором классе:

public delegate void UInt64Delegate1(UInt64 num);
public delegate void UInt64Delegate2(UInt64 num);

public event UInt64Delegate1 UInt64Event;


Затем в методе класса пишем одно из:

UInt64Event += new UInt64Delegate1(UInt64Method);//OK

UInt64Event += new UInt64Delegate2(UInt64Method);//Compile-time error:Operator '+=' cannot be applied to operands of type 'FramesTest.Form1.UInt64Delegate1' and 'FramesTest.Form1.UInt64Delegate2'

UInt64Event += (UInt64Delegate1)(new UInt64Delegate2(UInt64Method));//Compile-time error:Cannot convert type 'FramesTest.Form1.UInt64Delegate2' to 'FramesTest.Form1.UInt64Delegate1'

UInt64Event += (UInt64Delegate1)(System.Delegate)(new UInt64Delegate2(UInt64Method)); //Run-time error: InvalidCastException: Unable to cast object of type 'UInt64Delegate2' to type 'UInt64Delegate1'.


Вопрос: почему, казалось бы, очевидно-идентичные типы данных делегатов не преобразуются друг в друга?
Re: Преобразование типов делегатов
От: ie Россия http://ziez.blogspot.com/
Дата: 25.04.06 02:16
Оценка: 17 (1) +1
Здравствуйте, AkaSaint, Вы писали:

AS>Вопрос: почему, казалось бы, очевидно-идентичные типы данных делегатов не преобразуются друг в друга?


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

class A
{
    int i;
}
class B
{
    int i;
}

[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
static void Main(string[] args)
{
    A a;
    a = new A(); //OK
    a = (A)new B(); //Compile-time error:Cannot convert type 'B' to 'A'
    a = (A)(object)new B(); //Run-time error: InvalidCastException: Unable to cast object of type 'B' to type 'A'
}


Где проблема в этом коде вы понимаете?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Превратим окружающую нас среду в воскресенье.
Re: Преобразование типов делегатов
От: Mab Россия http://shade.msu.ru/~mab
Дата: 25.04.06 02:27
Оценка:
Здравствуйте, AkaSaint, Вы писали:

AS>Вопрос: почему, казалось бы, очевидно-идентичные типы данных делегатов не преобразуются друг в друга?

Потому что типы это разные даже несмотря на совпадение сигнатур.
Преобразование типов делегатов
От: Аноним  
Дата: 25.04.06 10:34
Оценка:
Другими словами надо понимать что делегат — это на самом деле класс!!!!
Так должно быть более понятно!


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re: Преобразование типов делегатов
От: AkaSaint  
Дата: 26.04.06 19:28
Оценка:
Да, теперь понятно! Я, с одной стороны, имел неосторожность забыть в этом вопросе, что делегат — это класс; с другой, меня сбило с панталыку явное упоминание в MSDN о том, что любой тип делегата можно привести к System.Delegate и обратно — я решил, что, раз это написано явно, то имеется в виду некий особый, свойственный именно делегатам, механизм приведения типов, который позволит привести делегат одного типа к делегату другого, но идентичного по сигнатуре типа.

Теперь вопрос: а есть ли способ все-таки выполннить такое приведение? Имеет место быть большое нежелание вызывать методы, на которые указывает делегат, через Invoke.
Re[2]: Преобразование типов делегатов
От: Mab Россия http://shade.msu.ru/~mab
Дата: 26.04.06 20:30
Оценка:
Здравствуйте, AkaSaint, Вы писали:

AS>Теперь вопрос: а есть ли способ все-таки выполннить такое приведение? Имеет место быть большое нежелание вызывать методы, на которые указывает делегат, через Invoke.


Можно создать новый делегат на основе метода Invoke старого делегата.

using System;

delegate void F1(int a, string b);
delegate void F2(int a, string b);

class Program
{
    public static void Main()
    {
        F1 f1 = Foo;
        F2 f2 = Convert(f1);
        f2(57, "test");    
    }
    
    static F2 Convert(F1 f1)
    {
        return f1.Invoke;
    }
    
    static void Foo(int a, string b)
    {
        Console.WriteLine("a = {0}, b = {1}", a, b);
    }    
}
Re: Преобразование типов делегатов
От: Lloyd Россия  
Дата: 26.04.06 20:58
Оценка:
Здравствуйте, AkaSaint, Вы писали:

AS>Вопрос: почему, казалось бы, очевидно-идентичные типы данных делегатов не преобразуются друг в друга?


Будь проще. Пиши.
UInt64Event += UInt64Method;

и все будет в шоколаде.
Re[3]: Преобразование типов делегатов
От: vhonest  
Дата: 26.04.06 21:17
Оценка: +1
Здравствуйте, Mab, Вы писали:

Mab>Можно создать новый делегат на основе метода Invoke старого делегата.


Или короче

using System;

delegate void F1(int a, string b);
delegate void F2(int a, string b);

class Program
{
    public static void Main()
    {
        new F2(new F1(Foo))(57, "test");
    }

    static void Foo(int a, string b)
    {
        Console.WriteLine("a = {0}, b = {1}", a, b);
    }
}


..что впринципе то же самое, что
        new F2(new F1(Foo).Invoke).Invoke(57, "test");
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Преобразование типов делегатов
От: vhonest  
Дата: 26.04.06 21:46
Оценка:
Здравствуйте, AkaSaint, Вы писали:

AS>Теперь вопрос: а есть ли способ все-таки выполннить такое приведение?

Приведение делегата одного типа к делегату другого типа (пусть даже они и имеют одинаковые сигнатуры) невозможно так же как и невозможно примедение типа A к типу B из разных веток наследования.

AS>Имеет место быть большое нежелание вызывать методы, на которые указывает делегат, через Invoke.

А в .NET подругому не получится — только через Invoke. Указатель на функцию, запакованную в экземпляре делегата, хранится где-то в структуре System.Delegate (и хорошо, что к нему нет доступа).
Тебе наверное хочется сложить все экземпляры делегатов с одинаковой сигнатурой в цепочку и потом вызвать их все разом (одним Invoke'ом). Обратно контроль типов! В одной цепочке все делегаты должны быть одного типа. Кругом засада

НО! Если заметить, что все экземпляры делегатов с одинаковой сигнатурой но разных типов имеют метод Invoke с этой же сигнатурой, то можно построить цепочку из этих Invoke'ов, завернутых в экземпляры делегатов одного типа.

Кажется невнятно написал..
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Преобразование типов делегатов
От: Александр Дольник Германия  
Дата: 15.05.07 08:33
Оценка:
Здравствуйте, ie, Вы писали:

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


AS>>Вопрос: почему, казалось бы, очевидно-идентичные типы данных делегатов не преобразуются друг в друга?


ie>Давайте разберемся сначала вот с таким кодом, казалось бы, никак не связанным с вашими делегатами:


ie>
ie>class A
ie>{
ie>    int i;
ie>}
ie>class B
ie>{
ie>    int i;
ie>}

ie>[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
ie>static void Main(string[] args)
ie>{
ie>    A a;
ie>    a = new A(); //OK
ie>    a = (A)new B(); //Compile-time error:Cannot convert type 'B' to 'A'
ie>    a = (A)(object)new B(); //Run-time error: InvalidCastException: Unable to cast object of type 'B' to type 'A'
ie>}
ie>


ie>Где проблема в этом коде вы понимаете?


я не понимаю. У меня скорее всего проблема похожего сорта. Получаю исключение InvalidCastException Unable to cast 'Type1' to 'Type1'. Type1 (условно) это делегат полученный вызовом Marshal.GetDelegateForFunctionPointer, при этом исходный указатель берется через WinApi. А потом при попытке Type1 type1 = (Type1) Marshal.GetDelegateForFunctionPointer(intPtr, typeof(Type1)) исключение. Если не кастировать, то исключений нет.
Re: Преобразование типов делегатов
От: _FRED_ Черногория
Дата: 15.05.07 09:03
Оценка:
Здравствуйте, AkaSaint, Вы писали:

AS>Вопрос: почему, казалось бы, очевидно-идентичные типы данных делегатов не преобразуются друг в друга?


Это такая ошибка проектировщиков C# Они пошли путём, который описал ie здесь
Автор: ie
Дата: 25.04.06
, вместо того, что бы сделать как-то так
Автор: VladD2
Дата: 23.03.07
.
Help will always be given at Hogwarts to those who ask for it.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.