Универсальный метод не может вызвать корректную перегрузку - PullRequest
6 голосов
/ 22 августа 2011

Примечание: я использую среду Mono, если это имеет значение.

Я пишу несколько тестов, и для этого у меня есть следующий универсальный метод:

static MemoryStream writeValue<T>(T inVal)
{
  MemoryStream ms = new MemoryStream();
  BinaryWriter bw = new BinaryWriter(ms);
  encode_any(bw, inVal);
  return ms;
}

Идея состоит в том, что это вызовет одну из моих encode_any перегрузок, которые делегируют специфичные для типа методы:

public static void encode_any(BinaryWriter writer, Int32 val) { encode_int32(writer, val); }
public static void encode_any(BinaryWriter writer, Int64 val) { encode_int64(writer, val); }
public static void encode_any(BinaryWriter writer, Float val) { encode_float(writer, val); }
...etc...
public static void encode_any(BinaryWriter writer, bool val) { encode_bool(writer, val); }

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

Однако, похоже, что компилятор пытается разрешить перегрузкуof writeValue, не зная, какой будет тип T, поэтому я получаю эту ошибку:

ошибка CS1502: наилучшее перегруженное соответствие метода для 'BinarySerialiser.encode_any (System.IO.BinaryWriter, bool)' имеет некоторыеошибка недопустимых аргументов CS1503: Аргумент '# 2' не может преобразовать выражение 'T' в тип 'bool'

Я заметил, что это не относится конкретно к bool- если я переставлю порядок моих функций encode_any, он всегда попытается использовать последнюю.Может быть, он просто пробует каждый из них, а затем выдает ошибку только тогда, когда у него заканчиваются альтернативы.

Этот вид кода будет хорошо работать в C ++, где writeValue компилируется только тогда, когда T известен, но это не 'Похоже, что здесь дело обстоит именно так, и я подозреваю, что это потому, что C # обрабатывает универсальные типы во время выполнения.

Могу ли я изменить свой подход, чтобы заставить это работать, и если да, то как?

Ответы [ 2 ]

8 голосов
/ 22 августа 2011

Это не C ++, а C #.Это означает, что ваш код не работает, потому что в универсальном классе в C # у вас есть доступ ко всем известным элементам параметров универсального типа.То, какие члены известны, определяется исключительно теми ограничениями, которые вы накладываете на параметры универсального типа.IIRC, в C ++ это немного по-другому.
В любом случае, в вашем случае нет никаких ограничений на T, поэтому компилятор ничего не знает об этом универсальном параметре.Однако нет никаких ограничений, которые позволили бы вам делать то, что вы хотите делать.
Если бы вы использовали .NET 4.0, вы могли бы использовать новое ключевое слово dynamic:

static MemoryStream writeValue<T>(T inVal)
{
  MemoryStream ms = new MemoryStream();
  BinaryWriter bw = new BinaryWriter(ms);
  dynamic dynamicValue = inVal;
  encode_any(bw, dynamicValue);
  return ms;
}

Поскольку вы используете Mono, я не думаю, что вы можете использовать это, поскольку Mono еще не реализовал это ключевое слово.
Похоже, Mono уже реализовал DLR, см. Ссылку из paolo ниже.

1 голос
/ 22 августа 2011

Ваша проблема в том, что разрешение перегрузки выполняется во время компиляции, а не во время выполнения - в данном случае в следующей строке:

encode_any(bw, inVal);

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

См. Также Общее разрешение перегрузки

Мой подход, вероятно, заключается в создании перегрузки encode_any, которая принимает объект и определяет, какой метод вызывать во время выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...