As we saw in Section 14.10, for each operation on an interface, the proxy class contains a corresponding member function with the same name. To invoke an operation, you call it via the proxy. For example, here is part of the definitions for our file system from
Section 5.4:
The name operation returns a value of type
string. Given a proxy to an object of type
Node, the client can invoke the operation as follows:
This illustrates the typical pattern for receiving return values: return values are returned by reference for complex types, and by value for simple types (such as
int or
double).
You can add an idempotent qualifier to a Slice operation. As far as the signature for the corresponding proxy method is concerned
idempotent has no effect. For example, consider the following interface:
Because idempotent affects an aspect of call dispatch, not interface, it makes sense for the two methods to be mapped the same.
The parameter passing rules for the C# mapping are very simple: parameters are passed either by value (for value types) or by reference (for reference types). Semantically, the two ways of passing parameters are identical: it is guaranteed that the value of a parameter will not be changed by the invocation (with some caveats—see
page 995).
Given a proxy to a ClientToServer interface, the client code can pass parameters as in the following example:
Slice out parameters simply map to C#
out parameters.
Here is the same Slice definition we saw on page 455 once more, but this time with all parameters being passed in the
out direction:
Given a proxy to a ServerToClient interface, the client code can pass parameters as in the following example:
Some Slice types naturally have "empty" or "not there" semantics. Specifically, C# sequences (if mapped to
CollectionBase), dictionaries, strings, and structures (if mapped to classes) all can be
null, but the corresponding Slice types do not have the concept of a null value.
•
If you pass a C# null reference to a Slice structure that is mapped to a C# class as a parameter or return value, the Ice run time automatically sends a structure whose elements are default-initialized. This means that all proxy members are initialized to
null, sequence and dictionary members are initialized to empty collections, strings are initialized to the empty string, and members that have a value type are initialized to their default values.
This behavior is useful as a convenience feature: especially for deeply-nested data types, members that are structures, sequences, dictionaries, or strings automatically arrive as an empty value at the receiving end. This saves you having to explicitly initialize, for example, every string element in a large sequence before sending the sequence in order to avoid
NullReferenceExceptions. Note that using null parameters in this way does
not create null semantics for Slice sequences, dictionaries, or strings. As far as the object model is concerned, these do not exist (only
empty sequences, dictionaries, and strings do). For example, whether you send a string as
null or as an empty string makes no difference to the receiver: either way, the receiver sees an empty string.