Click here to Skip to main content
15,886,110 members
Articles / Programming Languages / C#
Article

C# Keywords, Part II: Type Conversion, Operators and Object Types

Rate me:
Please Sign up or sign in to vote.
4.44/5 (36 votes)
25 Dec 20028 min read 168K   91   4
In part II of this multipart tutorial, I describe the keywords that can loosely be catagorized as dealing with object types, operators and type conversions.

Introduction

In part II of this multipart tutorial, I describe the keywords that can loosely be categorized as dealing with object type, operators and type conversion.

Why Is This Useful To You?

My interest in this series of articles is to provide a concise repository for the entire collection of keywords in C#. I plan to use this myself as a reference, and hopefully you will find it useful too. In Part I[^], I provided an overview of all the keywords and described in detail, with some code examples, the keywords that can be considered modifiers to entities such as methods, parameters, etc.

In the "old" days, languages used to be taught differently: start with the keywords, then move into the syntax, and then start writing some basic (as in simple!) programs. This approach, while it doesn't satisfy the "immediate gratification" crowd is still a valid approach when trying to gain a well rounded understanding of a programming language.

Why Is This Better Than Microsoft's Help On Keywords?

The primary answer to that question is not so much that what I have to say is better, but that in some cases, I provide supplementary understanding that the help topics don't provide. Also, personally, I get tired of bouncing around from one link to another. Sometimes it's nice to see everything laid out in a contiguous way. Also, I find that the more ways a concept can be described, the better I'll understand it, and there's nothing better to test one's comprehension than by trying to explain it to someone else!

What Have I Learned?

In writing Part II, I've learned that unary operators appear (to this author) pretty much useless because operators are required to be static members. Also, binary operators are limiting (this is true for unary operators as well) because they cannot return references to objects. So much for implementing streams in C# or other features found in STL. It seems that without the ability to operate on information in the enclosing class, and without the ability to return references, C# will never support the nice capabilities of templates and STL that we've grown to love using C++ (of course, I could be wrong!).

I also learned a lot about the inner "logic" of C#, especially regarding the rules for implicit and explicit casts.

The Keywords

Following is a table of (almost all) the keywords in C#.

abstracteventnewstruct
asexplicitnullswitch
baseexternobjectthis
boolfalseoperatorthrow
breakfinallyouttrue
bytefixedoverridetry
casefloatparamstypeof
catchforprivateuint
charforeachprotectedulong
checkedgotopublicunchecked
classifreadonlyunsafe
constimplicitrefushort
continueinreturnusing
decimalintsbytevirtual
defaultinterfacesealedvolatile
delegateinternalshortvoid
doissizeofwhile
doublelockstackalloc 
elselongstatic 
enumnamespacestring 

Keywords dealing with object type and type conversions:

These are the keywords that will be discussed in this article:

  • as
  • explicit
  • implicit
  • is
  • operator
  • sizeof
  • typeof

The "as" Keyword

The as keyword attempts to convert one object to another, similar to a cast. If the conversion fails, a null is returned instead of an exception being thrown. For example:

C#
object n=123;
object obj="abc";

string s1=n as string;
string s2=obj as string;

Console.WriteLine("s1="+s1);
Console.WriteLine("s2="+s2);

results in:

s1=
s2=abc

Note that in some cases, the compiler will generate an error because it is attempting to do the cast at compile time.

C#
int i=123;
string s1=i as string;

results in a compiler error: "Cannot convert type 'int' to 'string' via a built-in conversion."

To illustrate the difference between a cast and using the as operator, note that the following code:

C#
string s3=(string)n;

generates an exception, whereas, when using the as operator, the string s1 was merely set to null.

Note that the as keyword contains an implicit "is" test, using the keyword described next.

The "is" Keyword

The is operator tests whether an object is of a particular type. For example:

C#
object n1=123;

bool b1=n1 is int;
bool b2=n1 is string;

Console.WriteLine("n1 is int ? "+b1.ToString());
Console.WriteLine("n1 is string ? "+b2.ToString());

Results in:

n1 is int ? true
n1 is string ? false

With the as keyword, the compiler would generate a compile time error if it could resolve the object cast at compile time. Similarly, the compiler will generate a warning if the is operator evaluates to true or false at compile time--meaning that the expression is always either true or false.

The "operator" Keyword

This keyword declares an operator on a class or structure. An operator does two things. The first is it performs an operation on one or two parameters, including a conversion from the parameter type to the resulting type. The second thing an operator does is to perform a conversion from one type to another. This capability is used in conjunction with the explicit and implicit keywords, and will be discussed in the next two sections. In this section, we'll look at operators that perform an operation.

Operators are always public and they are always static. An operator is therefore always specified as:

C#
public static ...

Unary Operators

A unary operator takes one operand and manipulates it. The operand must be of the same type as the containing class or struct. Because the operator function is declared as static, it cannot reference anything except the members in its operand. This differs from C++, and in my opinion, makes unary operators basically useless except in highly specialized cases where it actually means something to "add" or "subtract" the members of an operand.

For example:

C#
public class PointEx
{
    protected Point p;

    public PointEx() {p=new Point(0, 0);}
    public PointEx(int x, int y) {p=new Point(x, y);}
    public PointEx(Point p) {this.p=p;}

    public static int operator +(PointEx p)
    {
        return p.p.X+p.p.Y;
    }
}

can be used syntactically as:

C#
PointEx p=new PointEx(1, 2);
int n=+p;

which results in n=3. This seems fairly pointless. However, overloading the "negative", "not", "exclusive-or", "increment" and "decrement" unary operators may be useful in certain instances.

Binary Operators

Binary operators perform an operation on two operands. At least one of the operands must be of the the enclosing struct or the class. This mechanism prevents you from redefining built in operators, for example, public static int operator +(int a, int b) {return a + b -1;} is not legal. An example of a binary operator is:

C#
public class PointEx
{
    protected Point p;

    public PointEx() {p=new Point(0, 0);}
    public PointEx(int x, int y) {p=new Point(x, y);}
    public PointEx(Point p) {this.p=p;}

    public static PointEx operator +(PointEx p, int scalar)
    {
        return new PointEx(p.p.X+scalar, p.p.Y+scalar);
    }
}

PointEx p=new PointEx(1, 2);
p+=5;

The Cast Operator

The cast operator is, in my opinion, another fairly useless item because, unlike C++, it cannot return a reference. This means that you cannot cast perform a cast on an "l-value". For example:

C#
public class PointEx
{
   protected Point p;

   public static implicit operator Point(PointEx p)
   {
       return p.p;
   }

   public static PointEx operator +(PointEx p, int xlat)
   {
    ((Point)p).X+=xlat;
    ((Point)p).Y+=xlat;
    return p;
   }
}

In the operator + method, the ((Point)p.).X cast is illegal because the operator Point cast is not, and can not, as the language is currently defined, return a reference.

However, with the above code, we could of course write:

C#
Point pp=p;

and the compiler will dutifully and automatically invoke the cast operator which returns the Point member of PointEx.

The "implicit" Keyword

The above example uses the implicit keyword in the definition of the operator. This defines it as a cast, and one that will occur automatically without the programmer knowing it.

The "explicit" Keyword

The explicit keyword also defines a cast operation but requires that the programmer explicitly selects the cast that is to be performed. If the cast operation has been defined, the compiler will dutifully generate the code to invoke the cast. For example, (modifying the above class):

C#
public static explicit operator Point(PointEx p)
{
    return p.p;
}

Now, the implicit cast we used before generates a compiler error:

C#
Point pp=p;            // !!! compiler error !!!
Point pp2=(Point)p;        // works

What are the rules in determining whether a cast should be defined as implicit or explicit?

Microsoft has this to say on the subject:

By eliminating unnecessary casts, implicit conversions can improve source code readability. However, because implicit conversions can occur without the programmer's specifying them, care must be taken to prevent unpleasant surprises. In general, implicit conversion operators should never throw exceptions and never lose information so that they can be used safely without the programmer's awareness. If a conversion operator cannot meet those criteria, it should be marked explicit.

  • Rule 1: Don't throw an exception in an implicit cast
  • Rule 2: Don't lose information. This is why, for example:
    C#
    int i=5;        // an integer
    double d=i;        // no loss of information
    int j=d;        // oops--potential loss of information

    the statement int j=d generates a compiler error: "No implicit cast...".

The "sizeof" Keyword

The sizeof keyword can only be used in "unsafe" mode. It returns the size of the object. For example:

C#
int i=sizeof(short)

results in i=2.

Note: I am not sure why this keyword can only be used in "unsafe" mode. I assume that the reason this is an "unsafe" keyword is that the underlying "generic" Instruction Language (IL) requires compiler and platform specific information to resolve the size of an object--whether a simple type like an integer or, a complex type like an object with multiple derivations or interfaces.

The "typeof" Keyword

This keyword returns the type of an object (not an instance). To return the type of an instance, use the GetType member. For example:

C#
double d=0;
Type t1=d.GetType();
Type t2=typeof(double);

These two statements are equivalent, except that GetType is applied to the instance of an object, whereas typeof is applied to the definition of an object. The value of obtaining a Type at run time is in the richness of this object--it includes information regarding access (private or public), and whether the object is a class, an interface or an ANSI class (just to name a couple). The Type object also has methods to extract the type's members and methods. This can be useful in conjunction with functions in the System.Reflection namespace.

Conclusion

I hope this series of articles helps anyone interested in understanding the capabilities of C#!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Interacx
United States United States
Blog: https://marcclifton.wordpress.com/
Home Page: http://www.marcclifton.com
Research: http://www.higherorderprogramming.com/
GitHub: https://github.com/cliftonm

All my life I have been passionate about architecture / software design, as this is the cornerstone to a maintainable and extensible application. As such, I have enjoyed exploring some crazy ideas and discovering that they are not so crazy after all. I also love writing about my ideas and seeing the community response. As a consultant, I've enjoyed working in a wide range of industries such as aerospace, boatyard management, remote sensing, emergency services / data management, and casino operations. I've done a variety of pro-bono work non-profit organizations related to nature conservancy, drug recovery and women's health.

Comments and Discussions

 
GeneralTypeOf Pin
Justin Keyes5-May-05 7:13
Justin Keyes5-May-05 7:13 
GeneralDynamic Casting Pin
mgarwood10-Feb-03 4:47
mgarwood10-Feb-03 4:47 
GeneralUnary operators and casts Pin
Frank Hileman31-Dec-02 14:33
Frank Hileman31-Dec-02 14:33 
GeneralGood pair of articles, couple typos Pin
ozrug31-Dec-02 6:07
ozrug31-Dec-02 6:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.