Using ref for value types I chanced upon this code written by the Solution Architect for an MS CRM project and I am lost for words. Am I going crazy or is this code OK?

string returnedOptionSetStringValue=string.Empty;
int returnedInt = 0;

Utils.RetrieveOptionSetLabelOrValue(CRMAccess.xrmService, Contact.EntityLogicalName, "new_status", optionSetValue.Value, string.Empty, ref returnedOptionSetStringValue, ref returnedInt, CRMAccess.tracerService);


The method within the Utils class is as follows

public static void RetrieveOptionSetLabelOrValue(IOrganizationService CrmWebService, string EntityName, string AttributeName, int OptionSetValue, string optionSetText, ref string returnedText, ref int returnedNumber, ITracingService tracerService)
{
    string returnLabel = string.Empty;
    tracerService.Trace("starting in function ");
    OptionMetadataCollection optionsSetLabels = null;

    tracerService.Trace("in retrieve option set label with values:" + OptionSetValue + " and text " + optionSetText);

    optionsSetLabels = RetrieveOptionSetMetaDataCollection(ref CrmWebService, EntityName, AttributeName);


    foreach (OptionMetadata optionMetdaData in optionsSetLabels)
    {
        tracerService.Trace("now in loop with  " + optionMetdaData.Label.UserLocalizedLabel.Label + " and " + optionMetdaData.Value.Value);
        //we have number we need text from optionset
        if (OptionSetValue != 0)
        {
            if (optionMetdaData.Value == OptionSetValue)
            {
                returnedText = optionMetdaData.Label.UserLocalizedLabel.Label;
                break;
            }
        }
        //we have text we need number from optionset
        else if (optionSetText != String.Empty)
        {

            if (optionMetdaData.Label.UserLocalizedLabel.Label == optionSetText)
            {
                returnedNumber = optionMetdaData.Value.Value;
                break;
            }

        }
    }
}
To answer your question, to me this is an illegitimate use of ref on a value type parameter.

Here's why:

1) Legit usages of ref are when you need to keep track the value of ref parameter or when passing the value is expensive. e.g. when using recursion to traverse a tree and you need to keep track of its depth.

Node&lt;T&gt; FindNode(T root, int nodeValue, ref int depth);


2) The code by the Solution Architect looks confusing and weird because it should be using out parameters instead (not to mention that it smells and looks like it deserves some refactoring).

Unlike ref params, out params need not be initialized prior being passed; which is why returnedOptionSetStringValue and returnedInt are being initialized.

For further reading:
http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.80).aspx
https://stackoverflow.com/questions/1516876/when-to-use-ref-vs-out