문제

다음과 같은 방법을 보았습니다.

public void Foo(List<string> list)
{
    list.Add("Bar");
}

메소드에서 매개 변수를 수정하는이 모범 사례입니까?

이것이 더 나아지지 않습니까?

public List<string> Foo(List<string> list)
{
    // Edit
    List<string> newlist = new List<string>(list);
    newlist.Add("Bar");
    return newlist;
}

첫 번째 예제에 예상치 못한 부작용이있는 것처럼 느껴집니다.

도움이 되었습니까?

해결책

당신이 준 예에서, 첫 번째는 두 번째보다 나에게 훨씬 더 좋은 것 같습니다. 목록을 수락하고 목록을 반환하는 방법을보고, 첫 번째 가정은 그것이 새 목록을 반환하고 주어진 목록을 만지지 않는다고 가정 할 것입니다. 따라서 두 번째 방법은 예상치 못한 부작용이있는 방법입니다.

메소드의 이름이 적절하게 이름 지어지면 매개 변수를 수정하는 데 위험이 거의 없습니다. 이걸 고려하세요:

public void Fill<T>(IList<T> list)
{
    // add a bunch of items to list
}

"채우기"와 같은 이름을 사용하면 메소드가 목록을 수정할 것이라고 확신 할 수 있습니다.

다른 팁

솔직히 말하면,이 경우 두 방법 모두 다소 동일한 작업을 수행합니다. 둘 다를 수정합니다 List 그것은 통과되었습니다.

목표가 그러한 방법으로 불변 할 수없는 목록을 갖는 경우, 두 번째 예제는 List 그것은 전송 된 다음 Add 새로운 작업 List 그리고 그것을 돌려주십시오.

나는 c# nor .net에 익숙하지 않으므로 내 추측은 다음과 같은 선을 따라 할 것입니다.

public List<string> Foo(List<string> list)
{
    List<string> newList = (List<string>)list.Clone();
    newList.Add("Bar");
    return newList;
}

이런 식으로, Foo 메소드가 새로 생성됩니다 List 반환 및 원본 List 통과 된 것은 건드리지 않을 것입니다.

이것은 실제로 사양 또는 API의 "계약"에 달려 있으므로 경우 ListS를 수정할 수 있습니다. 첫 번째 접근 방식으로 진행하는 데 문제가 없습니다.

두 방법 모두에서 똑같은 일을하고 있습니다. 그중 하나만 같은 목록을 반환합니다.

그것은 내 생각에 당신이하는 일에 실제로 달려 있습니다. 무슨 일이 일어나고 있는지 문서화가 명확하게 확인하십시오. 당신이 그런 종류의 일이 있다면 사전 조건과 사후 조건을 작성하십시오.

실제로 매개 변수로 목록을 취하는 메소드가 목록을 수정하는 것은 실제로 예상치 못한 것이 아닙니다. 목록에서만 읽는 메소드를 원한다면 읽을 수있는 인터페이스를 사용합니다.

public int GetLongest(IEnumerable<string> list) {
    int len = 0;
    foreach (string s in list) {
        len = Math.Max(len, s.Length);
    }
    return len;
}

이와 같은 인터페이스를 사용하면 메소드가 목록을 변경하는 것을 금지 할뿐만 아니라 예를 들어 문자열 배열과 같이 인터페이스를 구현하는 컬렉션을 사용할 수 있으므로 더욱 유연 해집니다.

다른 언어에는 다음과 같습니다 const 메소드를 변경하는 것을 금지하기 위해 매개 변수에 적용 할 수있는 키워드. .NET에는 이에 사용할 수있는 인터페이스와 불변의 문자열이 있으므로 실제로 필요하지 않습니다. const 매개 변수.

확장 방법의 출현으로 부작용을 도입하는 방법을 다루는 것이 조금 쉬워졌습니다. 예를 들어, 당신의 예에서는 말하기 훨씬 더 직관적입니다.

public static class Extensions
{
  public static void AddBar(this List<string> list)
  {
     list.Add("Bar");
  }
}

그리고 그것을 가지고 전화하십시오

mylist.AddBar();

목록에 무언가가 일어나고 있음을 더 명확하게 만듭니다.

주석에서 언급했듯이, 이것은 목록에 대한 수정이 더 혼란 스러울 수 있기 때문에 목록에서 가장 유용합니다. 간단한 물체에서는 객체를 제자리에 수정하는 경향이 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top