Overloaded Assignment Operator Derived Class In C#

The latest version of this topic can be found at Assignment Operators.

Syntax

Assignment operators store a value in the object designated by the left operand. There are two kinds of assignment operations: simple assignment, in which the value of the second operand is stored in the object specified by the first operand, and compound assignment, in which an arithmetic, shift, or bitwise operation is performed prior to storing the result. All assignment operators in the following table except the = operator are compound assignment operators.

Assignment Operators

OperatorMeaning
=Store the value of the second operand in the object specified by the first operand (simple assignment).
*=Multiply the value of the first operand by the value of the second operand; store the result in the object specified by the first operand.
Divide the value of the first operand by the value of the second operand; store the result in the object specified by the first operand.
Take modulus of the first operand specified by the value of the second operand; store the result in the object specified by the first operand.
Add the value of the second operand to the value of the first operand; store the result in the object specified by the first operand.
–=Subtract the value of the second operand from the value of the first operand; store the result in the object specified by the first operand.
<<=Shift the value of the first operand left the number of bits specified by the value of the second operand; store the result in the object specified by the first operand.
>>=Shift the value of the first operand right the number of bits specified by the value of the second operand; store the result in the object specified by the first operand.
&=Obtain the bitwise AND of the first and second operands; store the result in the object specified by the first operand.
Obtain the bitwise exclusive OR of the first and second operands; store the result in the object specified by the first operand.
Obtain the bitwise inclusive OR of the first and second operands; store the result in the object specified by the first operand.

Operator Keywords

Three of the compound assignment operators have text equivalents. They are:

OperatorEquivalent
&=

There are two ways to access these operator keywords in your programs: include the header file , or compile with the /Za (Disable language extensions) compiler option.

The simple assignment operator (=) causes the value of the second operand to be stored in the object specified by the first operand. If both objects are of arithmetic types, the right operand is converted to the type of the left, prior to storing the value.

Objects of const and volatile types can be assigned to l-values of types that are just volatile or that are neither const nor volatile.

Assignment to objects of class type (struct, union, and class types) is performed by a function named operator=. The default behavior of this operator function is to perform a bitwise copy; however, this behavior can be modified using overloaded operators. (See Overloaded Operators for more information.)

An object of any unambiguously derived class from a given base class can be assigned to an object of the base class. The reverse is not true because there is an implicit conversion from derived class to base class but not from base class to derived class. For example:

Assignments to reference types behave as if the assignment were being made to the object to which the reference points.

For class-type objects, assignment is different from initialization. To illustrate how different assignment and initialization can be, consider the code

The preceding code shows an initializer; it calls the constructor for that takes an argument of type . Given the code

the assignment statement

can have one of the following effects:

  • Call the function operator= for , provided operator= is provided with a argument.

  • Call the explicit conversion function , if such a function exists.

  • Call a constructor , provided such a constructor exists, that takes a argument and copies the result.

The compound assignment operators, shown in the table in Assignment Operators, are specified in the form e1= e2, where e1 is a modifiable l-value not of const type and e2 is one of the following:

  • An arithmetic type

  • A pointer, if is + or –

The e1= e2 form behaves as e1= e1e2, but e1 is evaluated only once.

Compound assignment to an enumerated type generates an error message. If the left operand is of a pointer type, the right operand must be of a pointer type or it must be a constant expression that evaluates to 0. If the left operand is of an integral type, the right operand must not be of a pointer type.

The assignment operators return the value of the object specified by the left operand after the assignment. The resultant type is the type of the left operand. The result of an assignment expression is always an l-value. These operators have right-to-left associativity. The left operand must be a modifiable l-value.

In ANSI C, the result of an assignment expression is not an l-value. Therefore, the legal C++ expression is illegal in C.

Expressions with Binary Operators
C++ Operators
C++ Built-in Operators, Precedence and Associativity
C Assignment Operators

expression assignment-operator expression assignment-operator : one of = *= /= %= += –= <<= >>= &= ^= |=
// expre_Assignment_Operators.cpp // compile with: /EHsc // Demonstrate assignment operators #include <iostream> using namespace std; int main() { int a = 3, b = 6, c = 10, d = 0xAAAA, e = 0x5555; a += b; // a is 9 b %= a; // b is 6 c >>= 1; // c is 5 d |= e; // Bitwise--d is 0xFFFF cout << "a = 3, b = 6, c = 10, d = 0xAAAA, e = 0x5555" << endl << "a += b yields " << a << endl << "b %= a yields " << b << endl << "c >>= 1 yields " << c << endl << "d |= e yields " << hex << d << endl; }
// expre_SimpleAssignment.cpp // compile with: /EHsc #include <iostream> using namespace std; class ABase { public: ABase() { cout << "constructing ABase\n"; } }; class ADerived : public ABase { public: ADerived() { cout << "constructing ADerived\n"; } }; int main() { ABase aBase; ADerived aDerived; aBase = aDerived; // OK aDerived = aBase; // C2679 }
UserType1 A; UserType2 B = A;
UserType1 A; UserType2 B; B = A;

The correct title of this article is C# syntax. The substitution or omission of the # is due to technical restrictions.

Main article: C Sharp (programming language)

This article describes the syntax of the C#programming language. The features described are compatible with .NET Framework and Mono.

Basics[edit]

Identifier[edit]

An identifier is the name of an element in the code. There are certain standard naming conventions to follow when selecting names for elements.

An identifier can:

  • start with an underscore: _
  • contain an underscore: _
  • contain a numeral: 0123456789
  • contain both upper case and lower case Unicode letters. Case is sensitive (FOO is different from foo).

An identifier cannot:

  • start with a numeral
  • start with a symbol, unless it is a keyword (check Keywords)
  • contain more than 511 characters
  • contain @ sign in between or at the end

Keywords[edit]

Keywords are predefined reserved words with special syntactic meaning. The language has two types of keyword — contextual and reserved. The reserved keywords such as or may only be used as keywords. The contextual keywords such as or are only treated as keywords in certain situations.[1] If an identifier is needed which would be the same as a reserved keyword, it may be prefixed by the @ character to distinguish it. This facilitates reuse of .NET code written in other languages.[2]

C# keywords, reserved words
2
2
2
2
2
2
2
2
1[3]21 
1, 2 These are not actually keywords, thus (unlike actual keywords) it is possible to define variables and types using these names, but they act like keywords in certain new language constructs introduced in C# 2.0(1) and 3.0(2).

Using a keyword as an identifier:

string@out;// @out is an ordinary identifier, distinct from the 'out' keyword,// which retains its special meaning

Literals[edit]

Integers
decimal
hexadecimal
binary
Floating-point values
float
double
decimal
Dates
DateTime
Characters
char
Strings
String
,
Characters escapes in strings
Unicode character followed by the hexadecimal unicode code point
Null character1
Tab
Backspace
Carriage return
Form feed
Backslash
Single quote
Double quote
Line feed
1Strings in C# are not null terminated

Digit separators[edit]

This is a feature of C# 7.0.

The underscore symbol separates digits in number values for readability purposes. Compiler will ignore it.

intbin=0b1101_0010_1011_0100;inthex=0x2F_BB_4A_F1;intdec=1_000_500_954;doublereal=1_500.200_2e-1_000;

Generally, it may be put only between digit characters. It cannot be put at the beginning () or the end of the value ( or ), next to the decimal in floating point values (), next to the exponent character () and next to the type specifier ().

Variables[edit]

Variables are identifiers associated with values. They are declared by writing the variable's type and name, and are optionally initialized in the same statement.

Declare

intmyInt;// Declaring an uninitialized variable called 'myInt', of type 'int'

Assigning

intmyInt;// Declaring an uninitialized variablemyInt=35;// Assigning the variable a value

Initialize

intmyInt=35;// Declaring and initializing the variable

Multiple variables of the same type can be declared and initialized in one statement.

inta,b;// Declaring multiple variables of the same typeinta=2,b=3;// Declaring and initializing multiple variables of the same type

Local variable type inference[edit]

This is a feature of C# 3.0.

C# 3.0 introduced type inference, allowing the type specifier of a variable declaration to be replaced by the keyword , if its actual type can be statically determined from the initializer. This reduces repetition, especially for types with multiple generic type-parameters, and adheres more closely to the DRY principle.

varmyChars=newchar[]{'A','Ö'};// or char[] myChars = new char[] {'A', 'Ö'};varmyNums=newList<int>();// or List<int> myNums = new List<int>();

See also

Constants[edit]

Constants are immutable values.

[edit]

When declaring a local variable or a field with the keyword as a prefix the value must be given when it is declared. After that it is locked and cannot change. They can either be declared in the context as a field or a local variable. Constants are implicitly static.

This shows all the uses of the keyword.

classFoo{constdoubleX=3;Foo(){constintY=2;}}

[edit]

The keyword does a similar thing to fields. Like fields marked as they cannot change once initialized. The difference is that you can choose to initialize them in a constructor. This only works on fields. Read-only fields can either be members of an instance or static class members.

Code blocks[edit]

The operators are used to signify a code block and a new scope. Class members and the body of a method are examples of what can live inside these braces in various contexts.

Inside of method bodies you can use the braces to create new scopes like so:

voiddoSomething(){inta;{intb;a=1;}a=2;b=3;// Will fail because the variable is declared in an inner scope.}

Program structure[edit]

A C# application consists of classes and their members. Classes and other types exist in namespaces but can also be nested inside other classes.

method[edit]

Whether it is a console or a graphical interface application, the program must have an entry point of some sort. The entry point of the C# application is the method. There can only be one, and it is a static method in a class. The method usually returns and is passed command-line arguments as an array of strings.

staticvoidMain(string[]args){}// OR Main method can be defined without parameters.staticvoidMain(){}

A method is also allowed to return an integer value if specified.

staticintMain(string[]args){return0;}

Namespaces[edit]

Namespaces are a part of a type name and they are used to group and/or distinguish named entities from other ones.

System.IO.DirectoryInfo// DirectoryInfo is in the System.IO-namespace

A namespace is defined like this:

namespaceFooNamespace{// Members}

statement[edit]

The statement loads a specific namespace from a referenced assembly. It is usually placed in the top (or header) of a code file but it can be placed elsewhere if wanted, e.g. inside classes.

usingSystem;usingSystem.Collections;

The statement can also be used to define another name for an existing namespace or type. This is sometimes useful when names are too long and less readable.

usingNet=System.Net;usingDirInfo=System.IO.DirectoryInfo;

Operators[edit]

Operator categoryOperators
Arithmetic, , , ,
Logical (boolean and bitwise), , , , , , , ,
String concatenation
Increment, decrement,
Shift,
Relational (conditional), , , , ,
Assignment, , , , , , , , , ,
Member access
Indexing
Cast
Conditional
Delegate concatenation and removal,
Object creation
Type information, , ,
Overflow exception control,
Indirection and Address, , ,
Coalesce
Lambda expression

Operator overloading[edit]

Some of the existing operators can be overloaded by writing an overload method.

publicstaticFoooperator+(Foofoo,Barbar){returnnewFoo(foo.Value+bar.Value);}

These are the overloadable operators:

Operators
, , , , , , , Unary operators
, , , , , , , , , Binary operators
, , , , , Comparison operators, must be overloaded in pairs
  • Assignment operators ( etc.) are combinations of a binary operator and the assignment operator () and will be evaluated using the ordinary operators, which can be overloaded.
  • Cast operators () cannot be overloaded, but you can define conversion operators.
  • Array indexing () operator is not overloadable, but you can define new indexers.

See also

Conversion operators[edit]

The cast operator is not overloadable but you can write a conversion operator method which lives in the target class. Conversion methods can define two varieties of operators, implicit and explicit conversion operators. The implicit operator will cast without specifying with the cast operator () and the explicit operator requires it to be used.

Implicit conversion operator

classFoo{publicintValue;publicstaticimplicitoperatorFoo(intvalue){returnnewFoo(value);}}// Implicit conversionFoofoo=2;

Explicit conversion operator

classFoo{publicintValue;publicstaticexplicitoperatorFoo(intvalue){returnnewFoo(value);}}// Explicit conversionFoofoo=(Foo)2;

operator[edit]

The operator will attempt to do a silent cast to a given type. If it succeeds it will return the object as the new type, if it fails it will return a null reference.

Streamstream=File.Open(@"C:\Temp\data.dat");FileStreamfstream=streamasFileStream;// Will return an object.Stringstr=streamasString;// Will fail and return null.

Null coalesce operator[edit]

This is a feature of C# 2.0.

The following:

returnifNotNullValue??otherwiseValue;

is shorthand for:

returnifNotNullValue!=null?ifNotNullValue:otherwiseValue;

Meaning that if the content of variable is not null, that content will be returned, otherwise the content of variable is returned.

Control structures[edit]

C# inherits most of the control structures of C/C++ and also adds new ones like the statement.

Conditional structures[edit]

These structures control the flow of the program through given conditions.

statement[edit]

The statement is entered when the given condition is true. Single-line case statements do not require block braces although it is mostly preferred by convention.

Simple one-line statement:

Multi-line with else-block (without any braces):

Recommended coding conventions for an if-statement.

if(i==3){...}elseif(i==2){...}else{...}

statement[edit]

The construct serves as a filter for different values. Each value leads to a "case". It is not allowed to fall through case sections and therefore the keyword is typically used to end a case. An unconditional in a case section can also be used to end a case. See also how statement can be used to fall through from one case to the next. Many cases may lead to the same code though. The default case handles all the other cases not handled by the construct.

switch(ch){case'A':statement;...break;case'B':statement;break;case'C':// A switch section can have multiple case labels.case'D':...break;default:...break;}

Iteration structures[edit]

Iteration statements are statements that are repeatedly executed when a given condition is evaluated as true.

loop[edit]

while(i==true){...}

loop[edit]

do{}while(i==true);

loop[edit]

The loop consists of three parts: declaration, condition and increment. Any of them can be left out as they are optional.

for(inti=0;i<10;i++){...}

Is equivalent to this code represented with a statement, except here the variable is not local to the loop.

inti=0;while(i<10){//...i++;}

loop[edit]

The statement is derived from the statement and makes use of a certain pattern described in C#'s language specification in order to obtain and use an enumerator of elements to iterate over.

Each item in the given collection will be returned and reachable in the context of the code block. When the block has been executed the next item will be returned until there are no items remaining.

foreach(intiinintList){...}

Jump statements[edit]

Jump statements are inherited from C/C++ and ultimately assembly languages through it. They simply represent the jump-instructions of an assembly language that controls the flow of a program.

Labels and statement[edit]

Labels are given points in code that can be jumped to by using the statement.

start:.......gotostart;

The statement can be used in statements to jump from one case to another or to fall through from one case to the next.

switch(n){case1:Console.WriteLine("Case 1");break;case2:Console.WriteLine("Case 2");gotocase1;case3:Console.WriteLine("Case 3");case4:// Compilation will fail here as cases cannot fall through in C#.Console.WriteLine("Case 4");gotodefault;// This is the correct way to fall through to the next case.default:Console.WriteLine("Default");}

statement[edit]

The statement breaks out of the closest loop or statement. Execution continues in the statement after the terminated statement, if any.

inte=10;for(inti=0;i<e;i++){while(true){break;}// Will break to this point.}

statement[edit]

The statement discontinues the current iteration of the current control statement and begins the next iteration.

intch;while((ch=Console.Read())!=-1){if(ch==' ')continue;// Skips the rest of the while-loop// Rest of the while-loop...}

The loop in the code above reads characters by calling , skipping the statements in the body of the loop if the characters are spaces.

Exception handling[edit]

Runtime exception handling method in C# is inherited from Java and C++.

The base class library has a class called from which all other exception classes are derived. An -object contains all the information about a specific exception and also the inner exceptions that were caused. Programmers may define their own exceptions by deriving from the class.

An exception can be thrown this way:

thrownewNotImplementedException();

statements[edit]

Exceptions are managed within blocks.

try{// Statements which may throw exceptions...}catch(Exceptionex){// Exception caught and handled here...}finally{// Statements always executed after the try/catch blocks...}

The statements within the block are executed, and if any of them throws an exception, execution of the block is discontinued and the exception is handled by the block. There may be multiple blocks, in which case the first block with an exception variable whose type matches the type of the thrown exception is executed.

If no block matches the type of the thrown exception, the execution of the outer block (or method) containing the statement is discontinued, and the exception is passed up and outside the containing block or method. The exception is propagated upwards through the call stack until a matching block is found within one of the currently active methods. If the exception propagates all the way up to the top-most method without a matching block being found, the entire program is terminated and a textual description of the exception is written to the standard output stream.

The statements within the block are always executed after the and blocks, whether or not an exception was thrown. Such blocks are useful for providing clean-up code.

Either a block, a block, or both, must follow the block.

Types[edit]

C# is a statically typed language like C and C++. That means that every variable and constant gets a fixed type when it is being declared. There are two kinds of types: value types and reference types.

Value types[edit]

Instances of value types reside on the stack, i.e. they are bound to their variables. If you declare a variable for a value type the memory gets allocated directly. If the variable gets out of scope the object is destroyed with it.

Structures[edit]

Structures are more commonly known as structs. Structs are user-defined value types that are declared using the keyword. They are very similar to classes but are more suitable for lightweight types. Some important syntactical differences between a and a are presented later in this article.

The primitive data types are all structs.

Pre-defined types[edit]

These are the primitive datatypes.

Primitive types
Type nameBCL equivalentValueRangeSizeDefault value
integer−128 through +1278-bit (1-byte)
integer−32,768 through +32,76716-bit (2-byte)
integer−2,147,483,648 through +2,147,483,64732-bit (4-byte)
integer−9,223,372,036,854,775,808 through
+9,223,372,036,854,775,807
64-bit (8-byte)
unsigned integer0 through 2558-bit (1-byte)
unsigned integer0 through 65,53516-bit (2-byte)
unsigned integer0 through 4,294,967,29532-bit (4-byte)
unsigned integer0 through 18,446,744,073,709,551,61564-bit (8-byte)
signed decimal number−79,228,162,514,264,337,593,543,950,335 through
+79,228,162,514,264,337,593,543,950,335
128-bit (16-byte)
floating point number±1.401298E−45 through ±3.402823E+3832-bit (4-byte)
floating point number±4.94065645841246E−324 through
±1.79769313486232E+308
64-bit (8-byte)
Boolean or 8-bit (1-byte)
single Unicode character through 16-bit (2-byte)

Note: () is not a struct and is not a primitive type.

Enumerations[edit]

Enumerated types () are named values representing integer values.

enumSeason{Winter=0,Spring=1,Summer=2,Autumn=3,Fall=Autumn// Autumn is called Fall in American English.}

variables are initialized by default to zero. They can be assigned or initialized to the named values defined by the enumeration type.

Leave a Comment

(0 Comments)

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