Re[9]: Полиморфизм области видимости
От: Belsen  
Дата: 07.11.05 18:57
Оценка: 81 (2)
Здравствуйте, GlebZ, Вы писали:

S>>Бред. Не надо говорить о своих намерениях с помощью NameSpace.

GZ>Linq именно на этом и построен.
К сожалению, некоторая доля правды в этом есть.
Несмотря на то, что операторы из DLinq и тип, над которым они работают, Query<T> находятся в одном неймспейсе, и подключить их по отдельности нельзя, в некоторых случаях используемые операторы будут завить только от того, используется или нет некоторый неймспейс.

Предположим, есть код
namespace SomeInternals
{
    using System.Data.DLinq;

    public interface IStorage<T>
    {
        Query<T> GetData();
    }
}


Тогда
using System;
using System.Query;
using System.Data.DLinq;

using SomeInternals;

public static class Test
{
    public static T Second<T>(IStorage<T> storage)
    {
        return storage.GetData().Skip(1).First();
    }

}

и
using System;
using System.Query;
//using System.Data.DLinq;

using SomeInternals;

public static class Test
{
    public static T Second<T>(IStorage<T> storage)
    {
        return storage.GetData().Skip(1).First();
    }

}

скомпилируются по разному, в первом случае будет использован статический метод System.Data.DLinq.QueryExtensions.Skip, во втором — System.Query.Sequence.Skip.

S>>Неа. Я уже вижу миллион применений этой бессмысленной игрушке. И ни в одном из них не видится никаких проблем с одноименностью расширений. Я просто не захочу сосуществования двух разных экстеншнов с одинаковой сигнатурой.

GZ>А они уже есть. Linq, DLinq, XLinq.
XLinq и Linq вроде не пересекаются, а у Linq и DLinq сигнатура различается в типе this-параметра.

GZ>Я уже писал. Допустим, у меня есть класс работы с некоторой коллекцией объектов. Я не очень понимаю что эта коллекция объектов из-себя представляет. Это может быть IEnumerator от XLinq, или допустим от DLinq, или просто от Linq. Но абстрагироваться от того, с кем я работаю у меня возможности нет. Я могу работать только с одной из этих библиотек.

DLinq определяет специализированные версии операторов, которые работают над Query<T>, применить их на IEnumerable<T> просто так не получиться. В тех же случаях, когда нужно применить более общие операторы вместо более специализированных, можно воспользоваться ToSequence<T>, который просто понижает compile-time тип до IEnumerable<T>.

Пусть:
Query<T> query;

В этом случае будет использованны DLinq.Skip и DLinq.First:
query.Skip(10).First(e => e.Cost > 10)

В этом случае будет использованны DLinq.Skip и Linq.First:
query.Skip(10).ToSequence().First(e => e.Cost > 10)

В этом случае будет использованны Linq.Skip и Linq.First:
query.ToSequence().Skip(10).First(e => e.Cost > 10)
I might be wrong...
Re[9]: Полиморфизм области видимости
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.11.05 04:43
Оценка:
Здравствуйте, GlebZ, Вы писали:
GZ>Я уже писал. Допустим, у меня есть класс работы с некоторой коллекцией объектов. Я не очень понимаю что эта коллекция объектов из-себя представляет. Это может быть IEnumerator от XLinq, или допустим от DLinq, или просто от Linq. Но абстрагироваться от того, с кем я работаю у меня возможности нет. Я могу работать только с одной из этих библиотек.
Гм. Я так и не могу понять в чем use case. Как это ты не понимаешь, что представляет из себя коллекция объектов? У коллекции есть тип. Есть статически декларированный тип, и гарантированно совместимый с ним рантайм тип. Я плохо понимаю объяснения типа "мне над работать с коллекцией". Слово "работать" не имеет семантики. Что ты хочешь сделать с этой коллекцией, и почему нельзя это сделать нормальным способом?
GZ>А они уже есть. Linq, DLinq, XLinq.
Неправда. Они построены именно нормальным образом. Только Linq дает работать с интерфейсами, предоставляя fallback-реализацию запросов. В DLinq и XLink методы реализованы прямо в классах. Никакой неоднозначности не возникает.
S>>Боюсь, я не смогу продолжать конструктивную дискуссию ежели ты не представишь сценарии использования, в которых это было бы полезно. Про ToDB/ToXML я на своем уровне понимания уже ответил.
GZ>Назови метод ToStorage. Достаточно абстрактное название которое абстрагирует вызывающего от знания внутренностей используемой библиотеки экстеншинов.
Ок, назовем его просто Save.
Реализуем ровно один екстеншн, который выберет соответствующий сторадж на основе app.config.
S>>Бред. Не надо говорить о своих намерениях с помощью NameSpace.
GZ>Linq именно на этом и построен.
Где ты это увидел?
S>>Более того, я считаю дурным тоном играть с областями видимости в таких целях и безо всяких екстеншнов.

GZ>Не-а. Тут наглядность классов реализаций. Но нельзя же запретить полностью работать через интерфейсы IDBxxxxx и абстрагироваться от типа бд.

Никто и не собирается этого делать.
GZ>И при этом у тебя есть рычажок проверить с какой базой работаешь, и учесть это в конкретных местах. Чего не присутсвует в Linq.
Все там присутствует, что надо.
S>>Плевание — это и есть собсно "перекрытие" дефолтной реализации.
GZ>Не понял что ты здесь имел ввиду.
Я имею в виду, что екстеншн как бы предоставляет дефолтную реализацию некоторого метода для семейства классов. При этом каждый класс может реализовать этот метод, и он "перекроет" метод екстеншна для себя.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Полиморфизм области видимости
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.11.05 06:45
Оценка: 18 (1)
Здравствуйте, Belsen, Вы писали:

B>К сожалению, некоторая доля правды в этом есть.


B>скомпилируются по разному, в первом случае будет использован статический метод System.Data.DLinq.QueryExtensions.Skip, во втором — System.Query.Sequence.Skip.

Погоди, а где определен IStorage<T> ? Если в System.Data.DLinq (как я предполагаю), то второй пример просто не скомпиляется, и проблемы не будет.

Тут самое главное — что нет попытки определить два екстеншна для одного и того же класса/интерфейса.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[11]: Полиморфизм области видимости
От: Belsen  
Дата: 08.11.05 14:54
Оценка: 42 (1)
Здравствуйте, Sinclair, Вы писали:

B>>К сожалению, некоторая доля правды в этом есть.

B>>скомпилируются по разному, в первом случае будет использован статический метод System.Data.DLinq.QueryExtensions.Skip, во втором — System.Query.Sequence.Skip.
S>Погоди, а где определен IStorage<T> ? Если в System.Data.DLinq (как я предполагаю), то второй пример просто не скомпиляется, и проблемы не будет.
В приведенном примере — в SomeInternals.

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

Кроме того, есть полные имена классов:
using System;
using System.Query;
using System.Data.DLinq; // влияет на выбор оператора Skip

public static class Test
{
    public static T Second<T>(System.Data.DLinq.Query<T> query)
    {
        return query.Skip(1).First();
    }
}

Есть алиасы:
using System;
using System.Query;
using System.Data.DLinq; // влияет на выбор оператора Skip
using BloodyQuery = System.Data.DLinq.Query<int>;

public static class Test
{
    public static int Second(BloodyQuery query)
    {
        return query.Skip(1).First();
    }
}


S>Тут самое главное — что нет попытки определить два екстеншна для одного и того же класса/интерфейса.

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

С другой стороны, это можно было и раньше:
namespace ImplementationOne
{
    using System;

    public static class Utils
    {
        public static void Do(object a, object b)
        {
            Console.WriteLine("One: {0} {1}", a, b);
        }
    }
}

namespace ImplementationTwo
{
    using System;

    public static class Utils
    {
        public static void Do(object a, object b)
        {
            Console.WriteLine("Two: {0} {1}", a, b);
        }
    }
}

namespace Test
{
    using System;
    //using ImplementationOne;
    using ImplementationTwo;
 
    public static class Program
    {
        public static void Main(string[] args)
        {
            Utils.Do("abc", 123);
        }
    }
}
I might be wrong...
Re[11]: Полиморфизм области видимости
От: GlebZ Россия  
Дата: 08.11.05 16:45
Оценка:
Здравствуйте, Sinclair, Вы писали:

Thanks all, я понял свои ошибки. Пошел учить азбуку.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[12]: Полиморфизм области видимости
От: Sinclair Россия https://github.com/evilguest/
Дата: 09.11.05 04:58
Оценка: +1
Здравствуйте, Belsen, Вы писали:

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

B>Наиболее вероятный вариант (и, пожалуй, единственный, который можно предполагать встретить на практике) — через определение членов другого типа, тип поля, свойства или возвращаемого значения метода.
В общем, все понятно. Собака порылась в способе выбора екстеншна. Анализ то идет просто: берем статический тип соответствующего выражения, и начинаем сканировать.
Метод может быть определен:
— у самого класса или одного из его предков
— как екстеншн для
-- класса,
-- одного из его предков
-- одного из интерфейсов, которые он реализует
-- одного из предков одного из интерфейсов, которые он реализует.
При этом очевиден выбор только в первом случае. При наличии нескольких одинаковых екстеншнов для различных, скажем так, таргетов из этого списка возможностей, у нас все начинает сильно зависеть от того, где ищутся эти екстеншны. И действительно, юзинги могут катастрофически влиять на ситуацию.

В банальных случаях, когда екстеншн определен в том же неймспейсе, где и его таргет, риск выбрать неправильный екстеншн минимален (только в тех случаях, когда тип таргета достается одним из указанных тобой способов).

B>Кроме того, есть полные имена классов:

B>
B>using System;
B>using System.Query;
B>using System.Data.DLinq; // влияет на выбор оператора Skip

B>public static class Test
B>{
B>    public static T Second<T>(System.Data.DLinq.Query<T> query)
B>    {
B>        return query.Skip(1).First();
B>    }
B>}
B>

B>Есть алиасы:
B>
B>using System;
B>using System.Query;
B>using System.Data.DLinq; // влияет на выбор оператора Skip
B>using BloodyQuery = System.Data.DLinq.Query<int>;

B>public static class Test
B>{
B>    public static int Second(BloodyQuery query)
B>    {
B>        return query.Skip(1).First();
B>    }
B>}
B>


B>Тем не менее, в общем случае ничто не мешает использовать только один из них, и подменять реализацию заменой использования одного экстеншина другим, хоть это и не кажеться хорошей идеей.


B>С другой стороны, это можно было и раньше:

Ага. см. пример в Re[7]: Полиморфизм области видимости
Автор: Sinclair
Дата: 07.11.05
.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.