Translating Objective-C to C#: Objective-C Blocks and C# Delegates

In the introduction to this series, I mentioned that C# delegates should not be confused with Objective-C delegates, the latter of which is a design paradigm, the former of which is executable code that can be assigned to a property or variable. The closest correlation to a C# delegate is an Objective-C block, and very close it is indeed. The syntax for an Objective-C block looks kind of scary to the C# developer at first, so I will attempt to explain that syntax here.

So what does a block look like in Objective-C? Here is what a block declaration looks like:

int (^addNumbers)(int a, in b);
addNumbers = ^(int a, int b) {
    int sum = a + b;
    return sum;
}

Or it could be done in one step:

int (^addNumbers)(int a, in b) = ^int(int a, int b) {
    int sum = a + b;
    return sum;
}

This declares a block named addNumbers with a return type of int that takes two int arguments. In the one step example, the return type is indicated in the definition as there was no declaration to define it. Compare to a delegate in C#, where you first define the delegate type and then you can use that type to declare a variable that can be passed around as an argument:

delegate int AddNumbers(int a, int b);
AddNumbers sumTwoNumbers = delegate(int a, int b) {
    int sum = a + b;
    return sum;
};

Note that there is no “Type” for a block in Objective-C. The “Type” is gleaned from the particular combination of return type and argument type(s), whereas in C# you are declaring a delegate type with the name AddNumbers. The caret, ^, is the key to identifying a block in Objective-C. It is placed immediately before the name of the block. When we are assigning code to the block name, the name can be left off as the compiler can glean the name from the variable that the block is getting assigned to. Also the return type does not have to be specified in the definition, and sometimes even the argument names can be left out, but not the argument types.

You can also have anonymous blocks just like you can have anonymous delegates in C#. If there is a function or method that requires an Objective-C block, you can pass it like this:

functionThatRequiresABlockArgument(^(int a, int b) {...});

As compared to C#:

functionThatRequiresADelegateArgument(delegate(int a, int b) {...});

There is one odd case where the ^ will come before the return type. You would see this when assigning a block to a property of a class. For instance, if I had the following in the class declaration in Objective-C:

@property (nonatomic, copy) int (^equation)(int, int);

I would use the following syntax to assign a block to that property: (using the default Obj-C setter name, see my post on Obj-C methods )

[object setEquation:^int(int x, int y) {...}

Except for the above case, the ^ will directly precede either the block name or, if anonymous, it will precede the argument opening parenthesis. Although not an expert on the nitty gritty details, blocks seem to behave like delegates as far as the scope of variables defined in the same scope that the block is defined in. In other words, those variables will be available to the block like they are to a delegate.

So basically when you see that ^ symbol in Objective-C, you are dealing with a block and you can use a delegate in its place in C#.

Leave a Reply

Your email address will not be published. Required fields are marked *