Program Tip

C # 메서드의 반환 된 값을 처리하지 않아도 괜찮습니까?

programtip 2020. 11. 10. 22:10
반응형

C # 메서드의 반환 된 값을 처리하지 않아도 괜찮습니까? 이 예에서 모범 사례는 무엇입니까?


호기심에서 ... 어떤 값을 반환하지만 처리 / 사용하지 않는 메서드를 호출하면 어떻게됩니까? 그리고 우리는 때때로이 반환 된 값이 정말 클 수 있다고 기대합니다. 그 가치는 어디로 가는가? 심지어 만들어 졌습니까? 그렇다면 성능 문제 또는 발생할 수있는 다른 문제가 있습니까? (이런 상황에서 가장 좋은 방법은 무엇입니까?)

일부 데이터베이스 작업 (삽입, 업데이트)을 수행하고 DataTable 개체에 일부 데이터를 반환하는 메서드가 있다고 가정 해 보겠습니다. 또한이 DataTable 개체가 때때로 정말 클 수 있다는 것도 알고 있습니다.

public static Datatable InsertIntoDB(...) 
{
      // executing db command, getting values, creating & returning Datatable object...
      ...
      return myDataTable;
}

그리고이 메서드를 사용하면 다음과 같이 호출됩니다.

DataTable myDataTable = InsertIntoDB(...);
// this Datatable object is handled in some way

그러나 때때로 단순히 다음과 같이 :

InsertIntoDB(...);
// returned value not handled; Problem???

처음에는 시스템이 반환 된 값이 무시되고 문제를 일으키지 않는 것을 볼 수있을만큼 똑똑하다고 생각하지만 (단순히 릴리스 됨) 더 많은 경험이있는 사람으로부터 더 자세한 설명을 듣고 싶습니다. 나보다이 지역.


반환 된 값 (또는 참조 유형 인 경우 참조)이 스택으로 푸시 된 다음 다시 팝됩니다.

크지 않습니다.

반환 값이 관련이없는 경우 안전하게 수행 할 수 있습니다.

그러나 만일을 대비하여 관련성이 없는지 확인하십시오.

다음은 몇 가지 코드입니다.

    static string GetSomething()
    {
        return "Hello";
    }

    static void Method1()
    {
        string result = GetSomething();
    }

    static void Method2()
    {
        GetSomething();
    }

IL을 보면 :

방법 1 :

.locals init ([0] string result)
IL_0000:  nop
IL_0001:  call       string ConsoleApplication3.Program::GetSomething()
IL_0006:  stloc.0
IL_0007:  ret

방법 2 :

IL_0000:  nop
IL_0001:  call       string ConsoleApplication3.Program::GetSomething()
IL_0006:  pop
IL_0007:  ret

정확히 같은 수의 명령어. Method1에서 값은 로컬 문자열 결과 (stloc.0)에 저장되며 범위를 벗어나면 삭제됩니다. Method2에서 pop 작업은 단순히 스택에서 제거합니다.

In your case of returning something 'really big', that data has already been created and the method returns a reference to it; not the data itself. In Method1(), the reference is assigned to the local variable and the garbage collector will tidy it up after the variable has gone out of scope (the end of the method in this case). In Method2(), the garbage collector can get to work, any time after the reference has been popped from the stack.

By ignoring the return value, if it really isn't needed, the garbage collector can potentially get to work sooner and release any memory that's been assigned. But there's very little in it (certainly in this case), but with a long running method, hanging onto that data could be an issue.

But far-and-away the most important thing is to be sure that the return value that you're ignoring isn't something that you should be acting on.


EDIT: Softened the language very slightly, and clarified.

It's rarely a good idea to ignore the return value, in my experience - at least in cases where the return values are there to convey new information instead of simply being for convenience.

One example where I've seen it be okay:

int foo;
int.TryParse(someText, out foo);

// Keep going

Here foo will be 0 if either someText contained "0", or it couldn't be parsed. We may not care which was the case in which case the return value of the method is irrelevant to us.

Another example is in a dictionary - suppose you're trying to count the number of occurrences of each string. You can use:

int count;
dictionary.TryGetValue(word, out count);
dictionary[word] = count + 1;

If the word wasn't in the dictionary to start with, that's equivalent to there being a count of 0 - which is what will already happen as a result of calling TryGetValue.

As a counter-example, ignoring the value returned by Stream.Read (and assuming that it's managed to read all the data you asked for) is a common mistake.

If you don't need the return value and it will have taken a lot of effort to compute, it may be worth looking for something which will achieve the same desired side-effects without the extra computation - but there's no extra performance implication. I'd be more worried about the correctness of ignoring a return value than the performance.

EDIT: Other examples where it's okay to ignore the return value:

  • Some fluent interfaces, including StringBuilder; while StringBuilder.Append(x).Append(y); uses the first return value for the second call, very often the return value of a call will be ignored, e.g. when appending in a loop
  • Some collection calls can give return values which are sometimes ignored - e.g. HashSet<T>.Add which indicates whether the value was actually added, or was already present. Sometimes you just don't care.

But for the vast majority of the time, ignoring the return value of a method indicates that it's doing more than you need it to.


From a memory management point of view thats fine - if the calling function doesn't use it, it goes out of scope and gets garbage collected.

In this particular case DataTable does implement IDisposable so its not all 100% fine:

If the returned object implements IDisposable then its a good idea to dispose it, for example:

using (var retVal = InsertIntoDB(...))
{
    // Could leave this empty if you wanted
}

It depends on the returned value it self.

The compiler will generate that value in the caller method, So if the value is IDispolable or expose Close method or if it have resources that should be released, then you should not ignore it and dispose it properly, or else you may suffering from problems and memory leaks..

For instance, if the returned value is a FileStream and you did not close the stream, the file may not closed until your application is terminated, more over if your application try to open the file again, it may throw exception that indicates "The file is in used by another process". So you should be careful on that kind of returned object and never ignore it!


It's totally fine to ignore the return value.

However. The architectural design is, IMHO, not good. An insert method should not return anything at all (other than MAYBE true or false on success or failure). If one would need to get a new, updated, dataset then one should ask for it, i.e call some other method to do so.


The returned value is thrown away if not used, but it is created. It is perfectly reasonable not to use it ( although you should be ceratin that this is the right thing to be doing ), but if it takes a lot of resource to create, then this is wasted.

You may want to consider whether another method would be a better options, that doesn't create the return object at all.


To give a different perspective on things, I think that method should be redesigned. Take a look at the Command-Query separation.

Also, it's rarely a good idea to silently ignore a return value. Readers of the code might not have the original context of the author. They might think he just forgot to use it. If the return value is not important, better be explicit about this decision:

var ignoredReturnValue = InsertIntoDB(...);

Interestingly, Nemerle actually gives you a warning if you ignore a return value. To not get the warning, you have to be explicit about your decision and write:

_ = InsertIntoDB(...);

I'm certain that this doesn't cause any problems, otherwise C# wouldn't be a very reliable language.

I'm guessing the compiler isn't smart enough to optimize this. What most likely happens is the ordinary logic inside the function call is executed, e.g. creating the object and allocating memory for it. If a reference type is returned but not captured, garbage collection will free up the memory again.

As others have stated, from a design view ignoring the return value does indicate a problem and most likely you should be looking at the return value.


If your function do some changes to other objects (for exemple a DB), I think it's okay to not handle the returned object if you don't need it.


All this talk about whether it is okay to ignore returned types is not needed, we do it all the time anyway in C#. Lots of functions you use as if they are returning void are not returning void. Think about a common function like Button1.Focus()

Did you know that the .Focus() function returns a bool value? It returns true if it succeeded in focusing on the control. So you could test it as a bool by saying:

if (Button1.Focus == true) MessageBox.Show("Button Focused successfully."); else MessageBox.Show("Could not focus on the button, sorry.");

But normally, you don't do this. You just say: Button1.Focus();

and you're done. I could give a hundred other examples where we ignore return values, like when a function runs but also returns a reference to something it created, but you don't care about the reference, you just wanted it to do the action (or you just want to simply check whether there is a reference or if it is null)

The point is, we ignore return values all the time, even if you don't know it.

참고URL : https://stackoverflow.com/questions/6874855/is-it-ok-not-to-handle-returned-value-of-a-c-sharp-method-what-is-good-practice

반응형