1. C# / Говнокод #15723

    +134

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    foreach (Admin _admin in _admins.Where(a => a.Login == _login))
                    {
                        if (_admin.Password == _password)
                        {
                            SessionObj = new Al2AllAuth
                            {
                                AccessId = _admin.Type,
                                Ename = _admin.Name,
                                Whoid = _admin.Id
                            };
                            var _type = (AdminTypes) _admin.Type;
                            switch (_type)
                            {
                                case AdminTypes.FirstType:
                                    return RedirectToAction(c_adminActionName, c_userControllerName);
                                case AdminTypes.SecondType:
                                    if (string.IsNullOrEmpty(model.Page) || string.IsNullOrEmpty(model.Uid))
                                        throw new ArgumentException(InternalResources.EmptyPageOrUid, "model");
                                    return RedirectToAction(model.Page, new { uid = model.Uid });
                                default: 
                                    break;
                            }
                        }
                        else
                        {
                            return RedirectToAction(_errorActionName);
                        }
                    }

    Лямбда в foreach очен смутила... Зачем?

    Запостил: KonstantinK, 11 Апреля 2014

    Комментарии (23) RSS

    • А пароль, лежащий в БД открытым текстом, не смущает? :)
      Ответить
      • И где видно что он открытым текстом?
        Ответить
        • Жопой чую ;)

          И даже если там хеш - то без соли. Ибо соль надо как-то извлекать из записи о юзере, а тут этого не делают.

          P.S. Ну разве что там не рандомная соль, а нечто на основе логина.
          Ответить
    • И чем смутила? Нормальный алгоритм фильтрации, в Питоне так же сделано.
      .where() видимо возвращает коллекцию элементов, для которых лямбда вернула истину, а потом по этой коллекции итерируемся.

      А вот строка 3 - это да.
      Ответить
      • В приложениях на питоне нормальная практика, когда несколько админов с одним и тем же логином, но разными паролями? Да даже если так, кто мешал написать
        var _admin=_admins.Where(x=> x.Login==_login && x.Password=_password).FirstOrDefault();

        И никакого цикла вообще не нужно.
        Ответить
        • > несколько админов с одним и тем же логином
          admin 123456
          admin 654321
          Ответить
    • > Лямбда в foreach очен смутила... Зачем?
      Эта такая ловушка для того чтобы код был плохо модифицируемый. Вот захочется написать if(...) break; И всё. Будете кидать исключение. А темболее if(...) continue; написать не получится
      Ответить
      • > Вот захочется написать if(...) break
        > if(...) continue; написать не получится
        Какого хуя лешего в базе делают два админа с одинаковым логином? :)
        Этот foreach тут по сути как if юзается. И его тело исполняется по-любому или один раз, или вообще ни разу...
        Ответить
        • Обычно, это так делается:
          Admin admin = _admins.FirstOrDefault(a => a.Login == _login);
          if(admin==null) {/*Всё ок, все счастливы*/}
          else {...}

          Уже пару раз наталкивался на то, что коллегам лень перегрузки глянуть.
          Ответить
      • P.S. Ну и да - как эта лямбда влияет на управление циклом? Она ж тупо используется для фильтрации данных, которые попадают на вход foreach'у.
        Ответить
        • foreach (Admin _admin in _admins.Where(a => a.Login == _login))

          .where() возвращает коллекцию, удовлетворяющую условию, потом уже с ней работает foreach
          Ответить
          • единственное НО, эта лямбда с отложенным выполнением, поэтому если коллекция admins большая, то может занять некоторое время перед запуском foreach
            Ответить
            • Наоборот, из-за ленивости никакого тормоза перед запуском форыча не будет.
              Ответить
              • Будет. Перед первой итерацией форича на то время, пока не найдется первая запись, удовлетворяющая where().

                Но на самом деле - всем пофиг. Раз не юзают базу или хотя бы что-то более шустрое чем последовательный поиск - админов там по пальцам сосчитать можно, и никакого тормоза само собой не будет :)
                Ответить
          • вообще-то там проекция должна возвращаться, а не коллекция
            Ответить
            • http://msdn.microsoft.com/ru-ru/library/ttw7t8t6.aspx
              читаем документацию, если тебе будет так понятнее, то возвращается новая коллекция
              Ответить
              • Попробуй выполнить. Раз уж новая коллекция создаётся:
                var list=new List<String>();
                list.Add("1");
                list.Add("2");
                list.Add("3");
                foreach(String str in list)//Exception: Collection Was Modified; Enumeration Operation May Not Execute
                    if(str=="1") list.RemoveAt(2);
                Ответить
              • Или ты про сам исходный объект?
                String[] arr = new String[] { "a", "b", "c", };
                Int32 index = 0;
                foreach(String s in arr)
                {
                	IntPtr f1, f2;
                	GCHandle h1 = GCHandle.Alloc(s, GCHandleType.Pinned);
                	try
                	{
                		f1 = h1.AddrOfPinnedObject();
                	} finally
                	{
                		h1.Free();
                	}
                	GCHandle h2 = GCHandle.Alloc(arr[index], GCHandleType.Pinned);
                	try
                	{
                		f2 = h2.AddrOfPinnedObject();
                	} finally
                	{
                		h2.Free();
                	}
                	index++;
                	System.Diagnostics.Debug.Assert(f1 == f2);
                }
                Ответить
              • Так наглядней будет:
                class C1
                {
                	public String A = "A";
                	public String B = "B";
                }
                static void Main(String[] args)
                {
                	C1[] arr = new C1[] { new C1(), new C1(), new C1(), };
                	foreach(C1 s in arr)
                	{
                		s.A = "Y";
                		s.B = "Z";
                	}
                	Console.WriteLine(String.Join(";", Array.ConvertAll(arr, delegate(C1 item) { return "A="+item.A + ",B=" + item.B; })));
                }
                Ответить
              • http://ideone.com/ARMeIC
                проекция возвращается из Where, а дальше по ней уже работает foreach, т.к. она реализует итератор.
                Ответить
    • Bormand абсолютно прав, _admins.FirstOrDefault должно быть
      Ответить
      • Либо SingleOrDefault, если вдруг архитектура, по какой-то, причине позволяет неуникальные логины.
        Ответить
    • _Нужно _больше _подчёркиваний _!
      Ответить

    Добавить комментарий