[C#, Этюд] params vs. params
От: nikov США http://www.linkedin.com/in/nikov
Дата: 03.03.10 17:30
Оценка: 101 (6)
using System;

class B<T>
{
  public static void Foo(params T[] x) { Console.WriteLine(1); }
  public static void Foo(params T[][] x) { Console.WriteLine(2); }
}

class C
{
  static void Main()
  {
    B<int>.Foo();
  }
}


Скомпилируется ли программа? Если да, то что будет напечатано?
Re: [C#, Этюд] params vs. params
От: 18сс Россия  
Дата: 03.03.10 17:42
Оценка:
Здравствуйте, nikov, Вы писали:



N>Скомпилируется ли программа? Если да, то что будет напечатано?

Я думаю, что не скомпилируется.
Кодом людям нужно помогать!
Re[2]: [C#, Этюд] params vs. params
От: Димчанский Литва http://dimchansky.github.io/
Дата: 03.03.10 17:54
Оценка:
Здравствуйте, 18сс, Вы писали:

1>Я думаю, что не скомпилируется.


К сожалению компилируется и выводит 2.
Осталось обратиться к стандарту за разъяснениями о выборе метода.
Re[3]: [C#, Этюд] params vs. params
От: nikov США http://www.linkedin.com/in/nikov
Дата: 03.03.10 18:06
Оценка:
Здравствуйте, Димчанский, Вы писали:

Д>К сожалению компилируется и выводит 2.

Д>Осталось обратиться к стандарту за разъяснениями о выборе метода.

Да, в стандарте есть этому объяснение.
Можно даже вот так сделать

using System;

class B<T>
{
  public static void Foo(params T[] x) { Console.WriteLine(1); }
  public static void Foo(params T[][] x) { Console.WriteLine(2); }
  public static void Foo(params T[][][] x) { Console.WriteLine(3); }
}

class C
{
  static void Main()
  {
    B<int>.Foo();
  }
}
Re: [C#, Этюд] params vs. params
От: Пельмешко Россия blog
Дата: 03.03.10 18:14
Оценка:
Здравствуйте, nikov, Вы писали:

N>
N>  public static void Foo(params T[] x) { Console.WriteLine(1); }
N>  public static void Foo(params T[][] x) { Console.WriteLine(2); }
N>


N>Скомпилируется ли программа? Если да, то что будет напечатано?


Согласно 7.4.3.1, оба метода applicable in expanded form и какого-то лешего второй является better...

Ума не приложу почему между int[] и int[][] в таком же случае компилятор выбрать не сможет, а между T[] и T[][], где T — bounded generic type of enclosing generic class, выбирает второй... И ведь не важно чем будет являться T...



p.s. Ура, nikov вернулся!
Re: [C#, Этюд] params vs. params
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.03.10 18:47
Оценка: 1 (1) +3
Здравствуйте, nikov, Вы писали:

N>Скомпилируется ли программа? Если да, то что будет напечатано?


Традиционная (в таких случая) реклама движка вывода типов Nemerle .

В нем код:
using System;

module B[T]
{
  public Foo(params _x : array[T]) : void { WriteLine(1); }
  public Foo(params _x : array[array[T]]) : void { WriteLine(2); }
}

module Program
{
  Main() : void
  {
    B.[int].Foo(); // E: typing fails on ambiguity between overloads
  }
}


Выдаст сообщение об ошибке:
Main.n(13,5):Error: typing fails on ambiguity between overloads:
Main.n(13,5):Warning: hint:   Posible overload: method B.Foo(params _x : array[array[T]]) : void #VarArg
Main.n(6,3):Warning: hint: overload defination
Main.n(13,5):Warning: hint:   Posible overload: method B.Foo(params _x : array[T]) : void #VarArg
Main.n(5,3):Warning: hint: overload defination

Что, на мой взгляд, является оптимальным поведением.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [C#, Этюд] params vs. params
От: Mab Россия http://shade.msu.ru/~mab
Дата: 03.03.10 18:50
Оценка: 158 (7)
Вроде бы достаточно прозначно, если следовать интрукции

Обе function members являются applicable. Выбор между ними идет с помощью п. 14.4.2.2:

14.4.2.2 Better function member
Given an argument list A with a sequence of argument types {A1, A2, …, AN} and two applicable function
members MP and MQ with parameter types {P1, P2, …, PN} and {Q1, Q2, …, QN, MP},

Здесь, видимо, опечатка? Должно быть {Q1, Q2, ..., QN}?
Впрочем, не важно. У нас function members are applicable in expanded form, обе последовательности типов пустые, поскольку нет аргументов.

after expansion and type argument substitution,is defined to be a better function member than MQ if
• for each argument, the implicit conversion from AX to PX is not worse than the implicit conversion from
AX to QX, and
• for at least one argument, the conversion from AX to PX is better than the conversion from AX to QX.

Поскольку, как уже отмечено, последовательности пустые, то квантор существования не срабатывает, пока tie.

When performing this evaluation, if MP or MQ is applicable only in its expanded form, then PX or QX refers to a
parameter in the expanded form of the parameter list.

Полезный комментарий, но это не наш случай -- аргументов-то нет.

In case the expanded parameter types {P1, P2, …, PN} and {Q1, Q2, …, QN}, are identical,

Вот, это про нас. Одинаковые пустые последовательности.

the following tiebreaking rules are applied to determine the better function member by comparing the given uninstantiated
and unexpanded parameter types {R1, R2, …, RK} and {S1, S2, …, SL} of the function members MP and MQ

Ключевое слово -- uninstantiated and unexpanded. Для нас K = L = 1, R1 = T[], S1 = T[][]

respectively. In this case, the better function member is determined by the following rules:
• If one of MP and MQ is non-generic, but the other is generic, then the non-generic is better.

Не про нас.

• Otherwise, if one of MP and MQ is applicable in its non-expanded form (or has no params array) and the
other is applicable only in its expanded form (and has a params array), then the non-expanded method is
better.

Не про нас.

• Otherwise, if the numbers of parameters K in MP and L in MQ are different, then the method with more
parameters is better.Note that this can only occur if both methods have params arrays and are only
applicable in their expanded forms.

Не про нас.

• Otherwise, the number of parameters K in MP and L in MQ are the same, and if one method has more
specific parameter types, then that method is better.

А это про нас. T[] is more specific than T[][], что видно далее индукцией по построению типа.

The given parameter types {R1, R2, …, RK} are
defined to be more specific than the given parameter types {S1, S2, …, SL} if each given parameter RX is
not less specific than SX, and at least one given parameter, RX is more specific than SX. A type parameter
is less specific than a non-type parameter. Recursively, a constructed type is more specific than another
constructed type (with the same number of type arguments) if at least one type argument is more
specific and no type argument is less specific than the corresponding type argument in the other. An
array type is more specific than another array type (with the same number of dimensions) if the element
type of the first is more specific than the element type of the second.

Итак, T isless specific than T[], откуда T[] is less specific than T[][]. Дальше уже не важно.

• Otherwise, if one member is a lifted operator and the other member is an unlifted operator, then the
unlifted operator is better.
• Otherwise, neither method is better.


Спасибо за этюд
Re[5]: [C#, Этюд] params vs. params
От: nikov США http://www.linkedin.com/in/nikov
Дата: 03.03.10 19:12
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>

Mab>14.4.2.2 Better function member
Mab>Given an argument list A with a sequence of argument types {A1, A2, …, AN} and two applicable function
Mab>members MP and MQ with parameter types {P1, P2, …, PN} and {Q1, Q2, …, QN, MP},

Mab>Здесь, видимо, опечатка? Должно быть {Q1, Q2, ..., QN}?

В моем тексте все правильно:


А анализ совершенно верный!
Re[5]: [C#, Этюд] params vs. params
От: Пельмешко Россия blog
Дата: 03.03.10 19:12
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>А это про нас. T is more specific than T[], что видно далее индукцией по построению типа.


Я до этого дошёл, но завис на этих правилах , всё равно не понимаю почему T less specific than T[]:

o A type parameter is less specific than a non-type parameter.

o Recursively, a constructed type is more specific than another constructed type (with the same number of type arguments) if at least one type argument is more specific and no type argument is less specific than the corresponding type argument in the other.

o An array type is more specific than another array type (with the same number of dimensions) if the element type of the first is more specific than the element type of the second.


Поясните пожалуйста, какое из правил здесь действует.
Re[2]: [C#, Этюд] params vs. params
От: nikov США http://www.linkedin.com/in/nikov
Дата: 03.03.10 19:15
Оценка: 6 (1) :))
Здравствуйте, Пельмешко, Вы писали:

П>p.s. Ура, nikov вернулся!


Есть место, где я появляюсь более регулярно, там тоже можно найти много интересного: http://youtrack.jetbrains.net/issues/RSRP?q=by:nikov
Re[6]: [C#, Этюд] params vs. params
От: Mab Россия http://shade.msu.ru/~mab
Дата: 03.03.10 19:15
Оценка:
Здравствуйте, nikov, Вы писали:

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


Mab>>

Mab>>14.4.2.2 Better function member
Mab>>Given an argument list A with a sequence of argument types {A1, A2, …, AN} and two applicable function
Mab>>members MP and MQ with parameter types {P1, P2, …, PN} and {Q1, Q2, …, QN, MP},

Mab>>Здесь, видимо, опечатка? Должно быть {Q1, Q2, ..., QN}?

N>В моем тексте все правильно:

N>
Ага, понятно. Я на сайте ECMA подсмотрел, видимо они не обновляют стандарт:
www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf

N>А анализ совершенно верный!
Re[6]: [C#, Этюд] params vs. params
От: Mab Россия http://shade.msu.ru/~mab
Дата: 03.03.10 19:16
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Я до этого дошёл, но завис на этих правилах , всё равно не понимаю почему T less specific than T[]:

Вроде бы самое первое из списка. T -- это type parameter, T[] таковым не является.

П>

П>o A type parameter is less specific than a non-type parameter.

П>o Recursively, a constructed type is more specific than another constructed type (with the same number of type arguments) if at least one type argument is more specific and no type argument is less specific than the corresponding type argument in the other.

П>o An array type is more specific than another array type (with the same number of dimensions) if the element type of the first is more specific than the element type of the second.


П>Поясните пожалуйста, какое из правил здесь действует.
Re[7]: [C#, Этюд] params vs. params
От: Пельмешко Россия blog
Дата: 03.03.10 19:46
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>Здравствуйте, Пельмешко, Вы писали:

П>>Я до этого дошёл, но завис на этих правилах , всё равно не понимаю почему T less specific than T[]:
Mab>Вроде бы самое первое из списка. T -- это type parameter, T[] таковым не является.

Хм, интересно, то есть T остаётся для компилятора как type parameter, даже в constructed type...
Я первое правило сразу же пропустил, думая что оно действует только для generic-методов...

ИМХО это плохое поведение...
Я бы ограничил это правило type parameter'ами от generic-методов, так как там правило имеет смысл и интуитивно...
Но наверное это повлекло бы какие-нить проблемы
Re[3]: [C#, Этюд] params vs. params
От: Пельмешко Россия blog
Дата: 03.03.10 19:52
Оценка: +1 :))
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, Пельмешко, Вы писали:


П>>p.s. Ура, nikov вернулся!


N>Есть место, где я появляюсь более регулярно, там тоже можно найти много интересного: http://youtrack.jetbrains.net/issues/RSRP?q=by:nikov


Божетымой, 3645 issues
Бедные JetBrains....
Re[8]: [C#, Этюд] params vs. params
От: nikov США http://www.linkedin.com/in/nikov
Дата: 03.03.10 20:32
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Хм, интересно, то есть T остаётся для компилятора как type parameter, даже в constructed type...


Обрати внимание на слово uninstantiated. Сравниваются типы из исходных деклараций, игнорируя любые подстановки типов-аргументов.
Re[7]: [C#, Этюд] params vs. params
От: nikov США http://www.linkedin.com/in/nikov
Дата: 03.03.10 20:37
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>Ага, понятно. Я на сайте ECMA подсмотрел, видимо они не обновляют стандарт:

Mab>www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf

Насколько я знаю, версии C# 3.0, 4.0 и не проходили международную стандартизацию.
Re[4]: [C#, Этюд] params vs. params
От: Димчанский Литва http://dimchansky.github.io/
Дата: 04.03.10 10:23
Оценка:
Здравствуйте, nikov, Вы писали:

N>Можно даже вот так сделать


А можно еще и так:

void Main()
{
    var c1 = new C<object>();
    c1.A(1);
    c1.A();    
    
    var c2 = new C<int>();
    c2.A(1);
    c2.A();        
}

class C<T>
{
    public void A(object a)
    {
        Console.WriteLine("A(object a)");
    }

    public void A(T a)
    {
        Console.WriteLine("A<>("+typeof(T).Name+" a)");
    }
    
    public void A(params T[] a)
    {
        Console.WriteLine("A<>(params "+typeof(T).Name+"[] a)");
    }

    public void A(params T[][] a)
    {
        Console.WriteLine("A<>(params "+typeof(T).Name+"[][] a)");
    }
}
Re[4]: [C#, Этюд] params vs. params
От: Димчанский Литва http://dimchansky.github.io/
Дата: 04.03.10 10:40
Оценка:
А вот почему с шаблонными класами все компилится, а так:

void Main()
{
    var b= new B();
    b.A();
}

class B
{
    public void A(params int[] a)
    {
        Console.WriteLine("A(params int[] a)");
    }

    public void A(params int[][] a)
    {
        Console.WriteLine("A(params int[][] a)");
    }
}


и так:

void Main()
{
    var b= new B();
    b.A();
}

class B
{
    public void A<T>(params T[] a)
    {
        Console.WriteLine("A(params int[] a)");
    }

    public void A<T>(params T[][] a)
    {
        Console.WriteLine("A(params int[][] a)");
    }
}


нет?
Re[5]: [C#, Этюд] params vs. params
От: Mab Россия http://shade.msu.ru/~mab
Дата: 04.03.10 10:45
Оценка:
Здравствуйте, Димчанский, Вы писали:

Д>А вот почему с шаблонными класами все компилится, а так:


Д>
Д>void Main()
Д>{
Д>    var b= new B();
Д>    b.A();
Д>}

Д>class B
Д>{
Д>    public void A(params int[] a)
Д>    {
Д>        Console.WriteLine("A(params int[] a)");
Д>    }

Д>    public void A(params int[][] a)
Д>    {
Д>        Console.WriteLine("A(params int[][] a)");
Д>    }
Д>}
Д>

Здесь int[][] не является more specific по сравнению с int[]. Посмотри внимательно правила определения "more specific".

Д>и так:


Д>
Д>void Main()
Д>{
Д>    var b= new B();
Д>    b.A();
Д>}

Д>class B
Д>{
Д>    public void A<T>(params T[] a)
Д>    {
Д>        Console.WriteLine("A(params int[] a)");
Д>    }

Д>    public void A<T>(params T[][] a)
Д>    {
Д>        Console.WriteLine("A(params int[][] a)");
Д>    }
Д>}
Д>


Д>нет?

А здесь вообще другая проблема: компилятор не может вывести тип T. Стоит написать b.A<int>(), и все получится.
Re[6]: [C#, Этюд] params vs. params
От: Димчанский Литва http://dimchansky.github.io/
Дата: 04.03.10 11:19
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>Здесь int[][] не является more specific по сравнению с int[]. Посмотри внимательно правила определения "more specific".


А где можно скачать самую распоследнюю версию стандарта?
Пришла пора заменить занимательную физику Перельмана в туалете на стандарт C#.

Mab>А здесь вообще другая проблема: компилятор не может вывести тип T. Стоит написать b.A<int>(), и все получится.


Да, во втором случае поторопился с примером.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.