Что не так с приведенным ниже утверждением (C # 3.0 / Lambda) - PullRequest
1 голос
/ 12 мая 2010

что не так в приведенном ниже

Enumerable.Range(0, objEntityCode.Count - 1).Select(i => 
{ 
options.Attributes[i] = new EntityCodeKey 
{ 
EntityCode = objEntityCode[i].EntityCodes 
, OrganizationCode = Constants.ORGANIZATION_CODE }; 
})
.ToArray(); 

Бросая ошибка Аргументы типа для метода 'System.Linq.Enumerable.Select (System.Collections.Generic.IEnumerable, System.Func)' не могут быть выведены из использования. Попробуйте указать аргументы типа явно.

Но это работает

Enumerable.Range(0, objEntityCode.Count - 1).ToList().ForEach(i =>  
                { 
                    options.Attributes[i] = new EntityCodeKey 
                    { 
                         EntityCode = objEntityCode[i].EntityCodes 
                         , OrganizationCode = Constants.ORGANIZATION_CODE   
                    };  

                } 
             ); 

Использование C # 3.0.

Цель: я изучаю LINQ / LAMBDA и пытаюсь выполнить одну и ту же программу по-другому.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 12 мая 2010

Как я уже говорил в комментарии, ваше лямбда-выражение ничего не возвращает. Поэтому его нельзя использовать в проекции. Select предназначен для преобразования последовательности элементов одного типа в последовательность элементов другого типа. Вы не делаете никакого преобразования в своем лямбда-выражении - вы только что получили задание.

Теперь вы можете сделать это:

Enumerable.Range(0, objEntityCode.Count - 1).Select(i => 
{ 
    return options.Attributes[i] = new EntityCodeKey 
    { 
        EntityCode = objEntityCode[i].EntityCodes,
        OrganizationCode = Constants.ORGANIZATION_CODE
    }; 
})
.ToArray();

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

1 голос
/ 12 мая 2010

Посмотрите, что у вас внутри вызовов методов Select и ForEach:

options.Attributes[i] = new EntityCodeKey 
    { 
        EntityCode = objEntityCode[i].EntityCodes 
        , OrganizationCode = Constants.ORGANIZATION_CODE   
    };

Это, по сути, Action<int> - то есть код, который делает что-то, но не возвращает что-то. Вот почему это имеет смысл в ForEach, но не Select - Select ожидает (в данном случае) Func<int, T> - код, который возвращает что-то (некоторого типа T) , Так как вы просто присваиваете Attributes[i] новому EntityCodeKey, этот код не попадает в рамки того, что вы обычно находите в вызове Select.

Обратите внимание, что технически , приведенный выше код на самом деле будет возвращать что-то, а именно значение, хранящееся в options.Attributes[i], если вы удалите точку с запятой с конца. Зачем? Две причины:

  1. Лямбда-выражение из одной строки (не заканчивающееся точкой с запятой) возвращает то, к чему оно относится. Вот почему что-то вроде person => person.Name может фактически интерпретироваться как Func<Person, string>.
  2. Операция присваивания оценивается как присвоенное значение. Вот почему вы можете написать x = y = z - потому что y = z фактически переходит в новое присвоенное значение y.

Так что это правда: ваш код без точки с запятой на самом деле оценивается как options.Attributes[i]. Но написание кода таким способом было бы, на мой взгляд, довольно запутанным.

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