Re[23]: Функциональные типы (параллельная ветка)
От: gbear Россия  
Дата: 29.06.05 10:53
Оценка: 68 (3) +1 :)
Здравствуйте, eao197, Вы писали:

G>>См. код выше... Я думаю, что Влад просто уже устал повторять, что делегат это ТИП, и с этой точки зрения он как раз и не связан ни с каким экземпляром другого типа. Но экземпляр делегата конкретного типа, должен быть связан с объектом (исключая связь со статическими методами). Т.к. иначе, что Вы собераетесь через него "дергать, имея лишь "голую" ссылку на метод...


E>Ok. Давайте будем для четкости использовать "тип делегата" и "экземпляр делегата" (равно как "тип указателя на метод" и "экземпляр указателя на метод").


Добро...


E>Так вот я прекрасно понимаю, что "тип делегата" никак не связан к конкретным экземпляром объекта (так же, как и тип указателя на метод). Но вот экземпляр делегата (как мне уже объяснил AndrewVK) может быть либо связан со статическим методом, либо с нестатическим методом конкретного объекта (т.е., экземпляр делегата связан с конкретным объектом). Но не может быть экземпляра делегата, связанного с нестатическим методом, но не имеющего объекта. А это означает, что если в твоем примере мы создали экземпляр делегата для t.Format(), то связать этот же делегат с c.Format() мы уже не сможем. Так же мы не сможем сделать делегат для вызова метода Format у любого неизвестного пока объекта типа Text.


Мягко говоря не совсем так... Даже в таком тупом примере, я вам показал делегат, который одновременно связан и с t.Format() и с с.Format.

Еще раз, но другими словами...


            Drive c = new Drive();
            Text t = new Text();
            FormatDelegate dd = new FormatDelegate(c.Format); //Создали делегат, связанный с "c.Format"
            FormatDelegate td = new FormatDelegate(t.Format); //Создали делегат, связанный с "t.Format"
            FormatDelegate tdd = dd + td; //А этот делегат связан с уже и с тем и с другим.
            tdd(); //c.Format + t.Format;
            tdd -= dd; //Теперь ttd связан только с "t.Format";
            tdd();
            tdd -= td;// А теперь tdd не связан уже ни с чем. Т.е. равен null.
            if(tdd == null)
                Console.WriteLine("tdd is null");
            Console.ReadLine();




E>А вот в C++ мы можем создать экземпляр указателя на метод Format объектов типа Text, не имея самого объекта этого типа. И затем использовать этот указатель для вызова метода Format у любого объекта типа Text без пересоздания самого экземпляра указателя на метод.

E>И именно поэтому я считаю, что механизм указателей на методы в C++ является более общим, т.к. он:
E>1) позволяет как связать указатель с конкретным объектом (посредством дополнительных оберток, как в моем примере или средствами boost-а),
E>2) создавать экземпляр указателя на конкретный нестатический метод без наличия самого объекта.

E>В C# п.1 получается автоматом, т.к. для этого есть поддержка со стороны компилятора. В C++, можно сказать, такая поддержка так же есть со стороны boost.

E>А вот как получить реализацию п.2 в C#?

E>PS

E>Просьба не апелировать к тому, что экземпляры указателей на методы без объектов не нужны. Я их использую, значит мне нужны. И, имхо, их использую не только я.

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

Далее, собственно, по существу...

1. Поскольку делегат (как тип), ко всему прочему не превязан к конкретному типу — в отличие от... то он, таки, имхо, более общ.
2. Для того функционала (пункты 1 и 2) делегаты, собсвенно не нужны... Вот как это выглядит на "голом" рефлекшене:

using System;
using System.Reflection;

namespace ConsoleApplication
{
    class Formater
    {
        private int _id = 0;
        public Formater(int id)
        {
            _id = id;
        }

        public void Print()
        {
            Console.WriteLine(string.Format("Formater: {0}", _id));
        }
    }

    class Binder
    {
        private MethodInfo _method = null;
        public Binder(MethodInfo method)
        {
            _method = method;
        }

        public void Call(object o)
        {
            _method.Invoke(o, null);
        }
    }

    class MainClass
    {
        [STAThread]
        static void Main(string[] args)
        {
            Formater f1 = new Formater(1);
            Formater f2 = new Formater(2);
            Binder b = new Binder(typeof(Formater).GetMethod("Print")); //Типа, экземпляр "голого" указателя на метод Print класса Formater;
            b.Call(f1); //Вызываем print у f1;
            b.Call(f2); //Вызываем print у f2;
            Console.ReadLine();
        }
    }
}


Устроит?

---
С уважением, Сиваков Константин.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.