Почему лямбда-выражение принимает символ вместо строки

1

У меня есть следующая функция, использующая выражение лямбда:

Func<string, DateTime> GetDateFromFileName
               = fileName => Path.GetFileNameWithoutExtension(fileName)
                                 .Select(s => DateTime.ParseExact(s.Substring(s.Length - 8, 8), "yyyyMMdd", null));

но компилятор жалуется, что char не имеет .Length или .Substring(). Почему это решить, что s является char, а не string? И есть ли более элегантный способ сделать вышеупомянутую работу, чем бросать пару .ToString() s?

Func<string, DateTime> GetDateFromFileName
               = fileName => Path.GetFileNameWithoutExtension(fileName)
                                 .Select(s => DateTime.ParseExact(s.ToString().Substring(s.ToString().Length - 8, 8), "yyyyMMdd", null));

Как linq выбирает тип переменной для создания первой переменной в выражении лямбда?

Теги:
linq
lambda

3 ответа

5
Лучший ответ

GetFileNameWithoutExtension возвращает string которую вы затем выполняете. .Select в. Это означает, что вы собираетесь перечислять символы в строке, поскольку строка представляет собой массив символов.

Linq будет смотреть на используемый вами colection и использовать тип внутренних объектов.

Учитывая ваше редактирование, вы можете изменить его на это

Func<string, DateTime> GetDatesFromFileNames
           = fileName =>
{
    String filenamenoext = Path.GetFileNameWithoutExtension(fileName); 
    return DateTime.ParseExact(filenamenoext.Substring(filenamenoext.Length - 8, 8), "yyyyMMdd", null));
}
  • 0
    Хорошо, это имеет смысл. Так что я, вероятно, не должен использовать .Select тогда. Есть ли более подходящая опция, которая позволяет мне работать со всей строкой?
  • 1
    @ Я думаю, что будет проще вообще не использовать linq
Показать ещё 6 комментариев
3

Ну, потому что string является IEnumerable<char> и Select будет работать на char из string. Т.е. вы также можете сделать:

foreach(var c in "hello") {
    // c is a char
}

Сделайте то, что вы (возможно) хотите просто удалить ненужные LINQ Select:

Func<string, DateTime> GetDatesFromFileNames = fileName => {
    var tmp = Path.GetFileNameWithoutExtension(fileName);
    return DateTime.ParseExact(tmp.Substring(tmp.Length - 8, 8), "yyyyMMdd", null);
};

Не похоже, чтобы IEnumerable возвращался, поскольку у вас, скорее всего, есть только одна дата в имени файла?

  • 0
    Спасибо , но повторно вашего редактирования s не будет определен ...
  • 1
    @ Дан, ты прав, исправлено (я надеюсь), в любом случае, я думаю, что у тебя уже есть идея :)
1

Если я правильно читаю, переходя по возвращаемому значению Func<string, IEnumerable<DateTime>> вас есть список файлов с прикрепленными датами:

fileA20140101
fileA20140102
fileB20140101

И вам нужно получить некоторый результат, содержащий:

fileA: 01-01-2014
       02-01-2014
fileB: 01-01-2014

Однако ваш funtion принимает только одно имя fileName даже если имя содержит fileNames. Возможно ли, что string fileName параметра string fileName должна быть IEnumerable<string> fileNames вместо этого? Это может иметь большее значение для реализации вашей функции!

Обновление по комментариям

Таким образом, ваша функция возвращает только одно время.

static DateTime GetDateFromFileName(string fileName) {
     const string format = "yyyMMdd";
     string withoutExtension = Path.GetFileNameWithoutExtension(fileName);
     return DateTime.ParseExact(
            withoutExtension.Substring(withoutExtension.Length - format.Length), 
            format, null);

}

Func<string, DateTime> myFunc = GetDateFromFileName;
  • 0
    Так что произошла другая ошибка, она должна просто возвращать один DateTime . Мои извинения, как вы и предлагали ранее, я пытался реорганизовать его так, чтобы он работал только на одной string и возвращал один DateTime . Я редактировал вопрос
  • 0
    @ Дан ответ обновлен
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню