Удалите повторяющиеся, твердые кодированные циклы и условия в C#

Вот ваш код, использующий другой элемент

<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
</head>
<body>
<form id="form" method="post" action="phpfile.php">
    <input type="hidden" name="ids" value="somevalue" /><input type="submit" value="Go">
</form>

<div id="link" href="">link</div>

<script>
$(document).ready(function () {
    $('#link').on('click',function(){
    alert('a');
        $('#form').submit();
    });
});
</script>
</body>
</html>
8
задан Bill the Lizard 6 October 2011 в 00:45
поделиться

6 ответов

Вы используете.NET 3.5? Я уверен, что LINQ к Объектам сделал бы многое из этого намного более простым.

Другая вещь думать о состоит в том что, если у Вас есть много кода с общим шаблоном, где всего несколько вещей изменяются (например, "какое свойство я сравниваю?" затем это - хороший кандидат на общий метод, берущий делегата для представления того различия.

Править: Хорошо, теперь мы знаем, что можем использовать LINQ:

Шаг 1: Уменьшите вложение
Во-первых я вынул бы один уровень вложения. Вместо:

if (NewStep.Id != Guid.Empty && SavedStep.Id != Guid.Empty)
{
    // Body
}

Я сделал бы:

if (NewStep.Id != Guid.Empty && SavedStep.Id != Guid.Empty)
{
    return;
}
// Body

Ранние возвраты как этот могут сделать код намного более читаемым.

Шаг 2: Нахождение, что документы удаляют

Это было бы намного более хорошо, если Вы могли бы просто указать ключевую функцию к Счетному. Пересечься. Можно указать компаратор равенства, но создание одного из тех является болью, даже со служебной библиотекой. А-ч хорошо.

var oldDocIds = OldDocs.Select(doc => doc.DocId);
var newDocIds = NewDocs.Select(doc => doc.DocId);
var deletedIds = oldDocIds.Intersect(newDocIds).ToDictionary(x => x);
var deletedDocs = oldDocIds.Where(doc => deletedIds.Contains(doc.DocId));

Шаг 3: Удаление документов
Или используйте существующий цикл foreach или измените свойства. Если Ваши свойства имеют на самом деле список типов <T> затем, Вы могли бы использовать RemoveAll.

Шаг 4: Обновление и удаление пользователей

foreach (StepUser deleted in usersToDelete)
{
    // Should use SingleOfDefault here if there should only be one
    // matching entry in each of NewUsers/OldUsers. The
    // code below matches your existing loop.
    StepUser oldUser = OldUsers.LastOrDefault(u => u.UserId == deleted.UserId);
    StepUser newUser = NewUsers.LastOrDefault(u => u.UserId == deleted.UserId);

    // Existing code here using oldUser and newUser
}

Одна опция упростить вещи еще больше состояла бы в том, чтобы реализовать использование IEqualityComparer UserId (и один для документов с DocId).

7
ответ дан 5 December 2019 в 17:43
поделиться

Поскольку Вы используете, по крайней мере.NET 2.0, я рекомендую, чтобы реализация Равнялась и GetHashCode (http://msdn.microsoft.com/en-us/library/7h9bszxx.aspx) на StepDoc. Как подсказка к тому, как это может очистить Ваш код, у Вас могло быть что-то вроде этого:

 Collection<StepDoc> docstoDelete = new Collection<StepDoc>();
foreach (StepDoc oldDoc in OldDocs)
                    {
                        bool delete = false;
                        foreach (StepDoc newDoc in NewDocs)
                        {
                            if (newDoc.DocId == oldDoc.DocId)
                            {
                                delete = true;
                            }
                        }
                        if (delete) docstoDelete.Add(oldDoc);
                    }
                    foreach (StepDoc doc in docstoDelete)
                    {
                        OldDocs.Remove(doc);
                        NewDocs.Remove(doc);
                    }

с этим:

oldDocs.FindAll(newDocs.Contains).ForEach(delegate(StepDoc doc) {
                        oldDocs.Remove(doc);
                        newDocs.Remove(doc);
                    });

Это предполагает, что oldDocs является Список StepDoc.

2
ответ дан 5 December 2019 в 17:43
поделиться

Если и StepDocs и StepUsers реализуют IComparable <T>, и они хранятся в наборах, которые реализуют IList <T>, то можно использовать следующий вспомогательный метод упростить эту функцию. Просто назовите его дважды, однажды с StepDocs, и однажды с StepUsers. Используйте beforeRemoveCallback для реализации специальной логики, используемой, чтобы сделать ролевые обновления. Я предполагаю, что наборы не содержат дубликаты. Я не учел проверки аргумента.

public delegate void BeforeRemoveMatchCallback<T>(T item1, T item2);

public static void RemoveMatches<T>(
                IList<T> list1, IList<T> list2, 
                BeforeRemoveMatchCallback<T> beforeRemoveCallback) 
  where T : IComparable<T>
{
  // looping backwards lets us safely modify the collection "in flight" 
  // without requiring a temporary collection (as required by a foreach
  // solution)
  for(int i = list1.Count - 1; i >= 0; i--)
  {
    for(int j = list2.Count - 1; j >= 0; j--)
    {
      if(list1[i].CompareTo(list2[j]) == 0)
      {
         // do any cleanup stuff in this function, like your role assignments
         if(beforeRemoveCallback != null)
           beforeRemoveCallback(list[i], list[j]);

         list1.RemoveAt(i);
         list2.RemoveAt(j);
         break;
      }
    }
  }
} 

Вот образец beforeRemoveCallback для Вашего кода обновлений:

BeforeRemoveMatchCallback<StepUsers> callback = 
delegate(StepUsers oldUser, StepUsers newUser)
{
  if(oldUser.Role != newUser.Role)
    UpdatedRoles.Add(newUser.Name, newUser.Role);
};
1
ответ дан 5 December 2019 в 17:43
поделиться

Для какой платформы Вы нацелены? (Это будет иметь значение в ответе.)

Почему это - пустая функция?

Не был должен подпись быть похожей:

DiffResults results = object.CompareTo(object2);
0
ответ дан 5 December 2019 в 17:43
поделиться

Если Вы хотите скрыть обход древовидной структуры, Вы могли бы создать подкласс IEnumerator, который скрывает "ужасные" конструкции цикличного выполнения, и затем используйте интерфейс CompareTo:

MyTraverser t =new Traverser(oldDocs, newDocs);

foreach (object oldOne in t)
{
    if (oldOne.CompareTo(t.CurrentNewOne) != 0)
    {
        // use RTTI to figure out what to do with the object
    }
}

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

0
ответ дан 5 December 2019 в 17:43
поделиться

Использовать несколько списков в foreach очень просто. Сделайте следующее:

foreach (TextBox t in col)
{
    foreach (TextBox d in des) // here des and col are list having textboxes
    {
        // here remove first element then and break it
        RemoveAt(0);
        break;
    }
}

Он работает аналогично foreach (TextBox t в col && TextBox d в des)

0
ответ дан 5 December 2019 в 17:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: