Я соглашаюсь, что mmap'd файловый ввод-вывод будет быстрее, но в то время как Ваше сравнительное тестирование кода, разве встречный пример не должен быть несколько оптимизирован?
Ben Collins записал:
char data[0x1000];
std::ifstream in("file.bin");
while (in)
{
in.read(data, 0x1000);
// do something with data
}
я предложил бы также пробовать:
char data[0x1000];
std::ifstream iifle( "file.bin");
std::istream in( ifile.rdbuf() );
while( in )
{
in.read( data, 0x1000);
// do something with data
}
И кроме того, Вы могли бы также попытаться делать размер буфера тем же размером как одна страница виртуальной памяти, в случае, если 0x1000 не является размером одной страницы виртуальной памяти на Вашей машине... По моему скромному мнению, файловый ввод-вывод mmap'd все еще побеждает, но это должно сделать вещи ближе.
Проблема возникает из-за того, что операторы приведения ( перегружены) разрешаются во время компиляции. Попробуйте подумать, как реализован Cast. Готов поспорить, код выглядит так:
public static IEnumerable<T> Cast<T>(this IEnumerable source)
{
foreach(object element in source)
{
yield return (T)(object)element;
}
}
Вся информация, которая есть у компилятора, заключается в том, что ему нужно преобразовать объект к типу T. И для этого он будет использовать преобразование наследования по умолчанию. Пользовательский перегруженный оператор не будет использоваться. И в вашем примере int не является двойным, поэтому приведение не удастся.
Пример select:
source.Select(a => (double)a));
работает, потому что компилятор знает оба типа и может вызвать соответствующий перегруженный оператор.
Попробуйте использовать метод Convertall класса Array. Это дает вам явный контроль над преобразованием.
var doubleArray = Array.ConvertAll<int, double>(intArray, num => (double)num);
Это позволяет обойти возникшую внутреннюю ошибку.
Другие методы также дают вам явный контроль над процессом преобразования.