0% found this document useful (0 votes)
16 views60 pages

Ch 3

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views60 pages

Ch 3

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 60

Chapter Three

Object-Oriented Fundamentals in C#
3.1 Language fundamentals
• C# is a simple, modern, general-purpose, object-oriented
programming language developed by Microsoft together with the
.NET platform.
• C# is extremely powerful programming language and used in
millions of applications around the world.
• There is highly diverse software developed with C# and on
the .NET platform: office applications, web applications,
websites, desktop applications, mobile applications, games and
many others.
Reasons make C# a widely used
professional language:
•It is a modern, general-purpose programming language
•It is object oriented.
•It is component oriented.
•It is easy to learn.
•It produces efficient programs.
•It can be compiled on a variety of computer platforms.
•It is a part of .Net Framework.
C# - Program Structure
•A C# program consists of //Namespaces
using System;
the following parts: namespace ConsoleApplication1
{
• Namespace declaration class Program
{ static int sum; //Class attribute
• A class //Main method
static void Main(string[] args)
• Class methods (user defined) {
sum=new Program().UserInput(4,5);
• Class attributes Console.WriteLine(sum);
Console.ReadKey();
• A Main method }
//User defined method
• Statements and Expressions public int UserInput(int a, int b) {
return a+b;
• Comments }
}
}
C# - Important points
• It is worth to note the following points:
• C# is case sensitive.
• All statements and expression must end with a semicolon (;).
• The program execution starts at the Main method.
• Unlike Java, program file name could be different from the class
name.
3.1.1 Variables, Data Types and Operators in C#
A. Variable
 A variable is a container/storage of information, which
can change its value during execution.
 It provides means for:
• Storing information;
• Retrieving the stored information;
• Modifying the stored information.
 Variables are characterized by:
Type (of the information preserved in them), for example int;
Name (identifier), for example age;
Value (stored information), for example 25.
Variable Naming Rules
 Variable names can contain the letters a-z, A-Z, the digits 0-9 as well as the character '_'.
 Variable names cannot start with a digit.
 keywords of the C# language can’t be used as a variable names
 For example: base, char, default, int, object, this, null and many others cannot be used as
variable names.
Declaring & Initializing Variables
 Declaration: preparing a variable for storage

 Initialization: specifying an initial value.


 Setting value to variables at the time of their declaration
 <data type> <identifier> [= <initialization>]; E.g. string name =”Abenezer”;

 Implicitly typed variables (C# 3.0)

 Allows to declare a variable using “var” keyword

 The data type of variable is implicitly recognized with the type of value that is assigned to it

E.g. var x=10; //x is of type int var s=“Hello”; //s is of type string
var d=12.5f; //d is of type float var y; //y is invalid
B. Data types
 Data types: are sets of values that have similar characteristics.
 Data types are characterized by:

 Name – for example, int;

 Size (how much memory they use) – for example, 4 bytes;

 Default value – for example 0.

 Basic data types in C# are distributed into the following types:


• Integer types – sbyte, byte, short, ushort, int, uint, long, ulong;
• Real floating-point types – float, double;
• Real type with decimal precision – decimal;
• Boolean type – bool;
• Character type – char;
• String – string;
• Object type – object.
• These data types are called primitive (built-in types), because they are embedded in C#
language at the lowest level
Cont…
Type conversion: Boxing and UnBoxing
• UnBoxing
• Boxing
• If the value type which is converted
• If the value type is converted into a
into a reference type again converted
reference type, we call it boxing
back into a value type, we call it
• Boxing is 20 times costlier than UnBoxing
normal initialization. This is because • Boxing is 4 times costlier than normal
during boxing the following tasks
initialization. This is because when
will be done internally
UnBoxing is made the following tasks
1. Run time will search for the will be performed internally
respective data with the stack
1. Object referenced value is searched
2. A copy of this value is made into within the Heap
Heap
2. A copy of this is made onto Stack
3. Reference to this copy is
E.g.
maintained from the object
variable. int x=Convert.Toint32(obj1);//UnBoxing
E.g. int x=100;
Read about : Convert class methods and parsing
object obj1=x;//Boxing
Nullable values

• Introduced in C# 2.0 which allows storing the Null value under the Value
type
• By default Null value can be stored only under reference type but not value
types
• The advantage of storing Null values in value type provides improved
interaction while working with databases.
• Database allows storing of Null values both under value types and
reference types.
• To declare a Null value, the type name suffix with a question mark
Example
string name=null; //valid
int x=null; //invalid
int? x=null; //valid
C. Operators
 Operators in C# can be separated in several different categories:
 Arithmetic operators – they are used to perform simple mathematical operations.
-, +, *, /, %, ++, --
 Assignment operators – allow assigning values to variables. =, +=, -=, *=, /=, %=
 Comparison operators – allow comparison of two literals and/or variables. ==,!=,
>, <, >=, <=
 Logical operators – operators that work with Boolean data types and Boolean
expressions. &&, ||, !, ^
 Binary operators – used to perform operations on the binary representation of
numerical data. &, |, ^, ~, <<, >>
 Type conversion operators – allow conversion of data from one type to another.
(type), as, is, typeof, sizeof
 Conditional operator – allows to perform operations based on the evaluation of an
expression. (expression)?operation if true?operation if false;
3.1.2 Control Flow
1. Conditional statements 2. Loop statements
 if,  while loop
 if...else,  do…while loop
 if...else if and  for loop
 Nested if Statement  Nested loop
 Switch statement  for each loop

3. Jump statements
 Continue, Go to,
Return and break
1. Conditional statements
i. "if “Statement
if (Boolean expression)
{
Body of the conditional statement;
}

The expression in the brackets which follows the keyword if must return the
Boolean value true or false.
If the value is true, then the body of a conditional statement is executed.
If the result is false, then the operators in the body will be skipped.
ii. if...else iii. if...else if
Statement Statement
if (Boolean expression) if (Boolean expression)
{
{
Body of the conditional statement;
Body of the conditional statement;
}
} else if (Boolean expression)
else {
{ Body of the else statement;
Body of the else statement; }
Else
}
{
Body of the else statement;
}
iv. Nested "if" Statement
An if...else statement can exist within another if...else statement
 Syntax:
if (boolean-expression)
{
if (nested-expression-1)
{
// code to be executed
}
else
{
// code to be executed
}
}
v. Switch statement
switch (variable_to_be_checked)
{
case value_1: Switch-case chooses which part of the
statements; programming code to execute based
break; on the calculated value of a certain
case value_2: expression
statements;
break;
// …
// …

default:
statements;
break;
}
2. Loop statements
Enable us repeated execution of a sequence of operations
a. While Loop
• The body of the while loop may not be executed even once if
in the beginning the condition of the cycle returns false

while (condition)
{
loop body;
}
b. Do-While Loop

is similar to the while loop, but it checks the condition


after each execution of its loop body
Executes the loop at least once
do
{ int i=10,sum=0;
executable code; do {
} while (condition); sum+=i;
i--;
}while(i>0);
Console.WriteLine(sum);
c. For Loop

for (initialization; condition; update)


{
loop's body;
}
Example
for (int i = 0; i < 10; i++)
{
Console.WriteLine("i="+i);
}
d. For each Loop
is used to iterate over the elements of the collection. The collection may be an
array or a list.
It executes for each element present in the array.
Syntax

foreach(data_type var_name in collection_variable)


{
// statements to be executed int[] a_array = new int[] { 1, 2, 3, 4, 5, 6, 7 };
} // foreach loop begin
//it will run till the last element of the array
foreach (int items in a_array)
{
Console.WriteLine(items);
}
Basic differences between for and foreach loops
for loop executes a statement or a block of statement until the given
condition is false.
• Whereas foreach loop executes a statement or a block of
statements for each element present in the array and there is no
need to define the minimum or maximum limit.
In for loop, we iterate the array in both forward and backward
directions, e.g from index 0 to 9 and from index 9 to 0.
• But in the foreach loop, we iterate an array only in the forward
direction, not in a backward direction.
We can not obtain array index using ForEach loop
Foreach loops are not appropriate when you want to modify the
array
Arrays
Group of memory location that stores the same type of data
Starts at index 0 and ends at Size-1
double[] balance = new double[10];

One-dimensional arrays are also called vectors and two-


dimensional are also known as matrices.
Assigning value to arrays

You can assign values to individual array elements


 double[] balance = new double[10];
 balance[0] = 4500.0;
You can assign values to the array at the time of declaration,
like:
 double[] balance = { 2340.0, 4523.69, 3421.0};
Or
 int [] marks = new int[5] { 99, 98, 92, 97, 95};
 int [] marks = new int[] { 99, 98, 92, 97, 95};
2. Jump statements
continue goto break & return
int i = 10; int i = 10; public string UserInput(char inputLetter) {
for (; i > 0; i--) { nxt: string response = null;
switch (inputLetter)
if (i == 5){ if (i > 5) { {
continue; Console.Write(i + " "); case 'a':
Console.Write(i + " "); Console.ReadKey(); case 'A':
Console.ReadKey(); response = "Letter a/A is provided";
i--;
break;
} goto nxt; case 'b':
} } response = "Letter b is pressed";
break;
}
return response;
}
3.1.3 Methods and Their Types
3.1.3.1 Method
• A method is a member of a class which we’ll use to define some functionality.
• Methods allow you to modularize an app by separating its tasks into reusable
units.
• Motivations for modularizing an app with methods
• Software reuse—existing methods can be used as building blocks to create
new apps.
• Avoid repeating code.
• Making programs easier to test, debug and maintain
• Dividing an app into meaningful methods makes the app easier to debug and
maintain.
• A method is an action that has to be performed.
Cont …
• Syntax:
[<modifiers>] <type> <name> ([parameter definition])
{ //Statements
}
• []optional
• Modifier: Includes special keyword that can be used on a method like public, private,
static, protected, virtual, abstract, override etc.
• Type: used to specify the type of value it is going to return.
• Parameter: If required, we can pass parameters to a method.
• There are two types
1. Input parameters- used for brining a value into a method for execution
2. Output parameters- used for carrying a value out of the method for execution
• We can send a value out of a method for execution in two different ways.
• Using return types-carry only a single result out of the method
• Using output parameters- are capable of carrying multiple value out of a method
Passing Arguments: Pass-by-Value vs. Pass-by-Reference

• Two ways to pass arguments to functions in many programming


languages are pass-by-value and pass-by-reference.
• When an argument is passed by value (the default in C#), a copy of
its value is made and passed to the called function.
• When an argument is passed by reference, the caller gives the
method the ability to access and modify the caller’s original
variable.
• Passing a value-type variable to a method passes a copy of the
value.
Cont …
• Passing a reference-type variable passes the method a copy of the
actual reference that refers to the object.
• The reference itself is passed by value, but the method can still use
the reference it receives to modify the original object in memory.
• A return statement returns a copy of the value stored in a value-type
variable or a copy of the reference stored in a reference-type variable.
• In effect, objects are always passed by reference.
ref and out Parameters
• Applying the ref keyword to a parameter declaration allows you to
pass a variable to a method by reference
• The ref keyword is used for variables that already have been
initialized in the calling method.
• Preceding a parameter with keyword out creates an output
parameter.
• This indicates to the compiler that the argument will be passed by
reference and that the called method will assign a value to it.
• A method can return multiple output parameters.
Cont…
Parameter modifier Passed by
none Value
ref Reference
out Reference

•Syntax of a parameter:
([ref/out]<type> <varName> [=value] )

Note: Fields inside [ ] are optional.


Cont… static void Main(string[] args)
• Example {
MethodTester mt = new MethodTester();
using System; mt.m3(10);
mt.m3(10, 20);
class MethodTester
int x = 0, y = 0;
{
mt.m1(50,25, ref x, ref y);
public void m1(int a, int b, ref int c, ref int d) { Console.WriteLine("x= "+x);
c = a + b; int n, m;
d = a * b; mt.m2(60, 5, out n, out m);
} Console.WriteLine("n= " + n);
public void m2(int a, int b, out int c, out int d) Console.ReadKey();
{ }
c = a - b; }
d = a / b;
}
public void m3(int x, int y=30, int z=10)
{
Console.WriteLine(x+y+z);
}
Notes on Using Methods
• Three ways to call a method:
• Using a method name by itself to call a method of the same class
• Using a reference to an object, followed by the member-access
operator (.) and the method name to call a non-static method of
the referenced object
• Using the class name and the member-access operator (.) to call a
static method of a class
• Console.ReadLine()
• Math.Sqrt(900.0)
Cont…
• As you know, a method is invoked by a method call, and when
the called method completes its task, it returns control and
possibly a result to its caller.
• Three ways to return control to the statement that calls a method.
• Reaching the end of the method.
• A return statement without a value.
• A return statement with a value.
3.1.3.2 Method types
• The followings are some of the method types in C#.
Method type Description
Static method - A method accessed by the class name and the member-access operator.
Abstract method - A method that does not have an implementation in the class it is declared.
Virtual method - A method that will be overridden in another class.
Sealed method - A method that is restricted from being overridden by a derived class.
Private/protected/public/ - These methods are given their names as per their respective access modifier.
Internal/ProtectedInternal
method
Value returning or non-value - A method that returns or does not return something to its caller respectively.
returning method
Parametrize/non-Parametrize - A method with argument/s or without parameters respectively.
method
Recursive method - A method that calls itself.
Anonymous method - A method where its contents are directly written under the delegate itself while
creating its object.

* Constructors and static methods cannot be declared abstract or


virtual
3.1.4 Events
• In programming terms, an Event occurs when something special
happens.
• Inbuilt code gets activated when the event happens.
• The event is then said to be “Handled”.
• The Events that we’ll discuss in this section are called GUI
Events.
• They are things like clicking a mouse button, leaving a text
box, right clicking, and many more.
• Some of these events are covered in the following slides.
i. The Click Event for Buttons
• The click event gets activated when a button is clicked on.
• Examine the default code for a button:
private void button1_Click(object sender, EventArgs e)
{
}
• In between the round brackets, we have this:
object sender, EventArgs e
• The object keyword refers to the object which activated the event, a
button in this case. This is being placed in a variable called sender.
• EventArgs (short for event arguments) is a class and tells you which
event was raised. The letter “e” sets up a variable to use this class.
ii. The MouseDown Event
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button==MouseButtons.Right){
MessageBox.Show(“You clicked Right button");
}
else if (e.Button == MouseButtons.Left)
{
MessageBox.Show(“You clicked Left button");
}
}
iii. The KeyDown Event

private void textBox1_KeyDown(object sender, KeyEventArgs e)


{
if (e.KeyData == Keys.A)
MessageBox.Show("Letter A is pressed");
}
iv. The Leave Event

private void textBox1_Leave(object sender, EventArgs e)


{
if(textBox1.Text==""){
MessageBox.Show("You can't leave this box blank");
textBox1.Focus();
}
}
v. ListBox and ComboBox Events
private void listBox1_SelectedIndexChanged(object sender,
EventArgs e)
{
if (listBox1.SelectedIndex==2) //III Year
{
listCourse3();
}
}
private void listCourse3() {
listBox2.Items.Clear();
listBox2.Items.Add("RAD");
listBox2.Items.Add("PHP");
listBox2.Items.Add("JAVA");
}
3.2. Classes and objects
• A class is a collection of things which poses common similarities.
• It contains instance and non-instance members.
• Instance members are accessed through object of these instances class.
• It also has constructor/s and a destructor.
• It’ll not occupy any memory space and hence it is only logical representation of
data.
Some of class types
1. Abstract class
• A class under which we declare abstract method is referred to as abstract class.
• We can declare a class using abstract modifier.
• Syntax: abstract class <className>{
public abstract <type> <methodName>([parameters]);
}
Cont …
• An abstract class contains both abstract and non-abstract methods in it.
• If any child of abstract class want to consume non-abstract method of its
parent, first they require to implement all the abstract methods of parent.
• Creating an object of an abstract class is not possible.
Example
using System; static void Main(string[] args)
abstract class AbstractClass { {
public void add(int x, int y) { ChildClass cc = new ChildClass();
Console.WriteLine("x+y=" + (x + y)); cc.add(15,65);
Console.WriteLine(cc.mult(4,53));
}
Console.ReadKey();
public abstract int mult(int a, int b); }
} }
class ChildClass: AbstractClass{
public override int mult(int c, int d) {
return (c * d);
}
Cont …
2. Interface
• It contains only abstract member/s in it.
• The abstract members that are defined in the interface will be given
implementation under the child class as interface.
• It can not contain any variable in it.
• Every member of an interface is by default abstract.
• The default scope of an interface members is public.
• An interface can inherit from another interface if required but not
from any class.

• What are the differences between interface and abstract class?


Cont …
Example
using System;
public interface IntClass
{
void add(int x, int y);
}
class IntImpl:IntClass{
public void add(int x, int y) {
Console.WriteLine("x+y= "+(x+y));
}
static void Main(string[] args)
{
IntImpl im= new IntImpl();
im.add(15, 85);
Console.ReadKey();
}
}
Cont …
3. Concrete class
• Classes that can be used to instantiate objects are called concrete classes.
• Concrete classes provide the specifics that make it reasonable to instantiate objects.
• Concrete derived classes must provide implementations for every accessor (get and /or set)
declared in the abstract property.
4. Sealed class
• When you want restrict your class from being inherited by others, you can create the class
as sealed class.
• Syntax
<Access modifier> sealed class <className> { }
5. Partial class
• A class in which its code can be written in two or more files.
• To make any class as partial, use partial keyword.
• It provides flexibility in application development.
• It is possible to split the definition of a class or a struct or an interface over two or more
files.
Cont …
Example: partial class
Example: sealed class using System;
using System; public partial class PartialClass {
sealed class RestrictedClass int x, y;
{ public PartialClass(int x, int y) {
public void Display() { this.x = x;
Console.WriteLine("Inside a sealed class"); this.y = y;
} }
} }
//Error-cannot derive from sealed type public partial class PartialClass{
class ChildClass: RestrictedClass{ public void printXY() {
public void show() Console.WriteLine("x={0} and y={1}",x,y);
{ }
Console.WriteLine("Inside a child class"); }
} class partialClassTester{
static void Main(string[] args) static void Main(string[] args)
{ {
ChildClass cc = new ChildClass(); PartialClass pc = new PartialClass(50,60);
cc.show(); pc.printXY();
//cc.display(); //Error Console.ReadKey();
Console.ReadKey(); }
} }
}
3.3. Inheritance and Polymorphism
3.3.1 Inheritance
• Inheritance allows a new class to absorb an existing class’s members.
• A derived class normally adds its own fields and methods to represent a more
specialized group of objects.
• Inheritance saves time by reusing proven and debugged high-quality software.
• The direct base class is the base class which the derived class explicitly
inherits.
• An indirect base class is any class above the direct base class in the class
hierarchy.
• The class hierarchy begins with class object.
Cont …
• The is-a relationship represents inheritance.
• For example, a car is a vehicle, and a truck is a vehicle.
• New classes can inherit from a pre-built class in class libraries.
• Note that base classes are “more general,” and derived classes are “more
specific.”
• Objects of all classes that extend a common base class can be treated as
objects of that base class.
• However, base-class objects cannot be treated as objects of their derived
classes.
• A derived class can customize methods it inherits from its base class. In
such cases, the derived class can override (redefine) the base-class
method with an appropriate implementation.
Cont …
• A base class’s private members are not directly accessible by derived-
class methods and properties.
• A base class’s protected members can be accessed by members of
that base class and by members of its derived classes.
• Syntax
public class BaseClass{}
class DerivedClass : BaseClass {}
• A colon (:) followed a class name at the end of the class declaration
header indicates that the class extends the class to the right of the colon.
• Every C# class directly or indirectly inherits object’s methods.
• If a class does not specify that it inherits from another class, it implicitly
inherits from object.
Cont …
• Constructors are not inherited.
• The derived-class constructor, before performing its own tasks, invokes its
direct base class’s constructor.
• This is done either explicitly or implicitly.
• If the base class is derived from another class, the base-class constructor
invokes the constructor of the next class up in the hierarchy, and so on.
• Even if a class does not have constructors, the default constructor will call
the base class’s default or parameterless constructor.
Notes on using Inheritance
• In inheritance the execution of child class starts by invoking the default
constructor of its parent class.
• You can explicitly call the available parent’s parametrized constructor
by supplying the required value/s using base keyword from the child
class constructor.
class ParentClass{
public ParentClass (string str){ Console.WriteLine(str);}
}
class ChildClass:ParentClass{
public ChildClass(string st)
:base(st)
{ Console.WriteLine("But this is inside child class."); }
}
Cont …
• In inheritance child classes can access parent class members but a parent
class can never access child class members.
• Object of a child can be assigned to the variable of its parent class. But
using parents reference, it’s not possible to access child class members.
Example: DerivedClass cc=new DerivedClass(); BaseClass bc=cc;
• If required a parent class reference created using object of child can be
converted back into child reference again but not directly; we need to
perform an explicit operation.
Example: DerivedClass c= (DerivedClass)bc; //OR
DerivedClass c=bc as DerivedClass;
• Every class (predefined/user-defined) has a default parent i.e. the class
object defined under System namespace
• .Net supports only single inheritance through classes.
Access modifiers
• Used to provide restriction to members of a class to access in the same class or in the
derived class in the same project or different project.
• C# supports five types of access modifiers
• Private: Private members are accessible only within the same class.
• Protected: Protected members are accessible within the class and also in the derived
class which might be in same project or in different project.
• Internal: Internal members are accessible in within the same class and any class within
the same project.
• ProtectedInternal: ProtectedInternal members are accessible in any class within the
same project and also from the derived classes outside the project but not accessible
from the non-derived classes outside the project.
• Public: Public members are accessible in any class in any project.

* For a class the default access modifier is “Internal”.


3.3.2 Polymorphism
• The method/constructor behaves in different ways depending upon the inputs
received.
• Whenever the input changes automatically the output and behavior also
changes.
• Polymorphism can be implemented using three different approaches
1. Overloading (via method, operator, constructor overloading)
2. Overriding
3. Hiding
1. A. Method overloading
• It’s an approach which allows to define multiple methods in a class with the same name
changing their signature.
• Changing the signature sense we can change the number of parameter being passed or
type of parameters being passed into the method or order of parameter passed into the
method.
Cont …
• Example of overloaded method show()
public void show()
public void show(int x)
public void show(string x)
public void show(int x, int y)
• A change in the return type of a method will not be taken into consideration
in the case of overloading.
• Note: overloading is a feature that allows to define multiple behaviors to a
method.
• Ex. Console.WriteLine() method is an overloaded method that have 19
methods in it.
Cont …
1. B. Constructor overloading
• We can overload constructor of a class also .
• If a class contains multiple constructors in it, object of that class can be created using
any constructor available.
• Generally, parametrized constructors will be defined to initialize variables of a class
dynamically with values that are sent while creating object of the class.
• Zero argument constructors /default constructors are also used for initializing variables
of a class with default values.
1. C. Operator overloading
• We can define multiple behavior to an operator.
• ‘+’ is an overloaded operator which can be used both for addition and concatenation.
• Syntax
[<access modifier>] static <type> operator <Symbol> (<Param definitions>){
//statements
}
Cont …
2. Method overriding:
• If at all a parent class method is re-implemented under the child class exactly with the
same signature, we call is as method overriding.
• To override a parent class method under child class, first in the parent class method
must be declared as virtual; then only the child can override the method using
override modifier.
3. Method hiding:
• This is another approach using which parent classes method can be re-implemented
under the child class.
• In this case even if the parent class the method is not declared as virtual, re-
implementing that method under the child class is possible.
class ParentClass{ Using new keyword on the method
public void show() { } while implementing is only optional or
} else you will get a warning message
class ChildClass: ParentClass{ stating that the child class methods
public new void show() { } //Hiding hides parent classes method.
}
Types of polymorphism
• There are two type of polymorphism:
1. Compile time or static or early binding
• At the time of program compilation, the object of the class knows which polymorphic
method it has to invoke and method call gets bound with the method.
• All this happens only in case of method overloading because here each method will
have different signature.
• It is called early binding because binding is done with method call and method signature
at compilation time only.
2. Runtime or dynamic or late binding
• In this type, object of the class recognizes which polymorphic method it has to call in
runtime.
• Hence the object gets bound with that method while mapping at runtime we call it as
late binding.
• Method overriding and method hiding come under this category. This is because
multiple methods will have a same signature
Further reading assignments

• Classes Vs components
• Operations on array
• Properties and indexers
• Constructor types and destructor
• Delegates
• Multi-threading

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy