Good day. I find the following code:
public class DocumentViewModel
{
/// <summary>
/// implicit model
/// </summary>
/// <param name="document"></param>
public static implicit operator DocumentViewModel(Document document)
{
return new Document
{
Id = document.Id,
};
}
}
It is used as follows:
DocumentViewModel results;
try
{
using (var context = new DbContext())
{
var uow = new DocumentUoW(context);
Document doc = uow.FindById(id);
results = doc; //aquí me da el StackOverFlowException
}
return Ok(results);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
Calling the DocumentViewModel raises the following exception on the explicit cast:
System.StackOverflowException: 'Se produjo una excepción de tipo 'System.StackOverflowException'.'
The error does not show InnerException or StackTrace to trace, the debugger as soon as it gets there throws the error. I don't understand why it's happening, I'm trying to investigate but the error description is too generic to find anything to help me. Does anyone have an idea what's going on?
Thanks to @Gbianchi's comment, he got the error.
The error, in a nutshell, is that my class
DocumentViewModel
, in its implicit conversion, is expecting to return an object of typeDocumentViewModel
, when it is returning an object of typeDocument
, then, when returningDocument
, the constructor it is exiting from is called, causing a loop unexpected, which is what triggers the exception.To fix this, the implicit conversion should return
DocumentViewModel
, as follows:With this change, the program runs normally. Thank you very much for the help! :D
Let's try the following code on dotnetfiddle (it's just code to emulate the problem):
When executing the program, it gives us the following result:
With our intuition we can deduce that the problem is in this line but we do not have the slightest idea why a stack overflow is happening :
To find out in more detail what is really going on, let's convert the C# code to IL code using SharpLab . Click on this link to see the IL code.
In the end we are only interested in this part of the generated IL code:
We can translate the IL code above to C# to better understand what the compiler is doing:
This is crazy! The truth is yes. The reason for the stack overflow is precisely because the method is being called
op_Implicit
recursively without a base case.The compiler generated this erroneous code due to programmer oversight, as they said in the comments, when overloading the operator, the method must return an object of type
DocumentViewModel
.Following the corrections mentioned in Ronquillo 's response , the example code (the one that emulates the behavior of the problem) would look like this:
By converting the above code to IL :
Effectively, the compiler no longer generates any bad code. As you can see, the method
op_Implicit
does not call itself indefinitely. The stack overflow disappeared.The above IL code can be better understood like this:
Now the code generated by the compiler makes sense and the program will work correctly.