I recently helped a friend of mine code an application and at some point I created a method using a pass-by-reference parameter. Apparently this is new to him. I asked several other programmer friends that I know and most of them either know about it but never use it or don't know about it. So - here is a post about it.
To illustrate the usage of pass-by-reference, I will create to a simplistic example - where we want to calculate a loan amortization: with initial loan, interest rate, and loan period - and resulting in: monthly payment and total interest over loan term
So in code, without the pass-by-reference, we have to do this somewhat in 2 steps/methods:
decimal monthlyPayment = CalculateMonthlyPayment(initialLoan, rate, period); decimal totalInterest = CalculateTotalInterest(initialLoan, rate, period);With the definitions:
public decimal CalculateMonthlyPayment(decimal initialLoan, double rate, int period) { decimal result; // calculate monthly payment return result; } public decimal CalculateTotalInterest(decimal initialLoan, double rate, int period) { decimal result; // calculate interest return result; }
While the 2 steps thing is OK, but we know that we can optimize that better since both methods use the same parameter and both methods have a lot of similarity in their calculation. So it would be better if we can combine both methods - how can can we get 2 results with 1 methods? Maybe we should return the results in an array or make a "MortgageAmortization" class? Both ideas are OK and no doubt are also easily doable. But, I think this is also the right place to use pass-by-reference parameter in simplifying and optimizing our methods.
There are 2 ways to do pass-by-reference in C#: out or ref. The difference between them is small but important: argument passed to a ref parameter must be initialized - where out param does not have to be. You can read about ref and out further here.
So, using pass-by-reference, our code becomes something like this:
decimal monthlyPayment = 0; decimal totalInterest = 0; monthlyPayment = CalculateMortgage(initialLoan, rate, period, out totalInterest); // or you can use ref instead of out as long as the method signatures match // monthlyPayment = CalculateMortgage(initialLoan, rate, period, ref totalInterest);
public decimal CalculateMortgage(decimal initialLoan, double rate, int period, out totalInterest) { decimal result; // calculate monthly payment // set total interest // totalInterest = 12500; return result; }
2 comments:
I've been doing a lot of lua and that is one thing I love.. multiple return values.. its used very often in what is considered "well formed" lua
A call like this:
local success, header, items = model_characters:get( UID, AKey )
And inside:
function model_characters:get(u, a)
local path = u..filename
local exists, x = eveixutil:read(path)
if(exists) then
local h, i = translate(x, u)
for r,rows in pairs(h) do
for rname, rvalue in pairs(rows) do
if((rname=="localcachedseconds" and rvalue>os.time()) or _G.internet==false) then
return true, h, i
end
end
end
end
if(cacheAPI(u, a)) then
return self:get(u, a)
else
return false
end
end
This is one of those "preference" situations. I like the more "pure" functional approach of returning an entity (struct or class) with the data. TryParse functions follow the example that you're proposing, but after doing a little reading, I agree with what I read somewhere that out parameters are never needed.
I do fall back on what I learned of optimizing SQL Server development where output parameters are more efficient than returning a single row in a recordset. So if performance is your goal, then out/ref parameters may be more efficient. I would like to see some performance numbers comparing returning an entity vs out vs ref.
Post a Comment