More on iOS / XCode / Objective-C Migration Methods and Multiple Parameters to C#

6. May 2011 03:16 by Mrojas in General  //  Tags: , , , , , , , , , , , , , , ,   //   Comments (0)

On a previous post I was describing how some basic Objective-C elements were mapped to C#.
In particular I showed how the @interface and @implementation definitions are to be mapped in .Net, including basic properties.
In this post I will show a little about how methods are migrated.

There are several things to analyze when moving Objective-C code to C# it might be simple but can be a complicated
task. Objective-C is a language created under the inspiration of SmallTalk. And in Smalltalk programmer do not think of
method calls but instead of message sending and that is something to keep in mind when doing this migration.
Also all methods are virtual and even if there are access restriction in Objective-C I will map those methods to
public for simplicity sake.

In the previous post we had:

FIRSTFIRST

Fraction.h
#import <Foundation/NSObject.h>
@interface Fraction: NSObject {
    int numerator;
    int denominator;
}
-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
@end

And

Fraction.m

#import "Fraction.h"
#import <stdio.h>

@implementation Fraction
-(void) print {
    printf( "%i/%i", numerator, denominator );
}

-(void) setNumerator: (int) n {
    numerator = n;
}

-(void) setDenominator: (int) d {
    denominator = d;
}

-(int) denominator {
    return denominator;
}

-(int) numerator {
    return numerator;
}
@end

And that example shows properties and methods with no parameter. OK. Now lets just focus on methods with 0, 1 and more parameters.

MethodsExample.h

#import <Foundation/NSObject.h>
@interface MethodsExample: NSObject {

}
-(void) print;
-(int) multiplyByTwo: (int) n ;
-(void) multiplyTwoNumers: (int) a andSecondNumber: b;
@end
 
MethodsExample.m
#import "MethodsExample.h"
#import <stdio.h>

@implementation MethodsExample
-(void) print {
    printf( "Hola mundo\n" );
}

-(int) multiplyByTwo: (int) n {
    return n * 2;
} -(int) multiplyTwoNumbers: (int) a andSecondNumber (int) b { return a * b;
} @end
And calling those functions will be:
#import <stdio.h>
#import "MethodsExample.h"

int main( int argc, const char *argv[] ) {
    // create a new instance
    MethodsExample *m = [[MethodsExample alloc] init];
    [m print]; 
int result; result = [m multiplyByTwo: 1]; result = [m multiplyTwoNumbers: 1 andSecondNumber: 5]; // free memory [m release]; return 0; }
This little example shows some of the particularities of Objective-C. 
In Objetive-C all parameters starting from the second parameter can have
what is called a label and labels are similar to namedParameter. Ok lets go ahead and map that class.
using System;

public class MethodsExample
{
    public virtual print() {
        Console.WriteLine("Hola mundo\n");
    }
    public virtual int multiplyByTwo(int n)
    {
      return n * 2;
    }
    //AproachOne
    public virtual int multiplyTwoNumber(int a,int andSecondNumber)
    {
        return a * andSecondNumber;
    }
    //AproachTwo
    //I just renamed as multiplyTwoNumber2 to avoid compilation errors.
    //The idea is that you will choose one of the two aproaches
    //or define a criteria for the instances where aproach one should be used
    //instead of approach two
    public virtual int multiplyTwoNumber(int a,int andSecondNumber)
    {
        int n = andSecondNumber;
        //This aproach will be better if you have a lot of code in the method
        //and you prefer to keep the original arg name
        return a * n;
    }

}
So the thing here is what to use as the parameter name, the label or the argument name. 
In the example you can see the two approaches in the multiplyTwoNumbers case.
 And calling the methods is simple and the named parameters syntax can be exploited.
using System;

public static class Program
{
    public static int Main(string[] argv ) {
        // create a new instance
        var m = new MethodsExample();
        m.print();
        int result;
        result = m.multiplyByTwo(1);
        result = m.multiplyTwoNumbers(1,andSecondNumber: 5); //using named parameters
        // free memory
        m.release();
        return 0;
    }
}
REMEMBER: This is just a glimpse of some mapping concepts from Objective-C to C#. 
There are many subtle details in this kind of migration and is my belief that only
an automated tool is able to process all those details in an effectively and more error-free
than a manual approach. For example in objective-c if m is null that will not cause any error if you
do something like [m print] and in C# that will throw an error. However a migration tool could determine
if the variable will have a value before its use and avoid adding unnecessary if (m!=null) statements.
We will examine this and other details in following posts. I hope this little examples give you enough information

for playing around migrating some Objective-C code. And if it gets too complicated just send me an email!!!

Categories