1. Trang chủ
  2. » Công Nghệ Thông Tin

Microsoft Visual C# 2010 Step by Step (P10) pptx

50 399 1
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Creating Components in C# 2010
Trường học Microsoft, https://www.microsoft.com
Chuyên ngành Computer Science
Thể loại Textbook
Năm xuất bản 2010
Thành phố Redmond
Định dạng
Số trang 50
Dung lượng 660,33 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

In other words, the compiler effectively converts the code Hour now = new Hour9; Hour postfix = now++; to this: Hour now = new Hour9; Hour postfix = now; now = Hour.operator ++now; //

Trang 1

Operator Constraints

You have seen throughout this book that C# enables you to overload methods when defining your own types C# also allows you to overload many of the existing operator symbols for your own types, although the syntax is slightly different When you do this, the operators you implement automatically fall into a well-defined framework with the following rules:

n You cannot change the precedence and associativity of an operator The precedence

and associativity are based on the operator symbol (for example, +) and not on the type (for example, int) on which the operator symbol is being used Hence, the expres- sion a + b * c is always the same as a + (b * c), regardless of the types of a, b, and c

n You cannot change the multiplicity (the number of operands) of an operator For

example, * (the symbol for multiplication), is a binary operator If you declare a *

operator for your own type, it must be a binary operator

n You cannot invent new operator symbols For example, you can’t create a new operator

symbol, such as ** for raising one number to the power of another number You’d have

to create a method for that

n You can’t change the meaning of operators when applied to built-in types For

example, the expression 1 + 2 has a predefined meaning, and you’re not allowed to

override this meaning If you could do this, things would be too complicated!

n There are some operator symbols that you can’t overload For example, you can’t overload the dot ( ) operator, which indicates access to a class member Again, if you could do this, it would lead to unnecessary complexity

Tip You can use indexers to simulate [ ] as an operator Similarly, you can use properties to

simulate assignment (=) as an operator, and you can use delegates to simulate a function call as

Trang 2

Chapter 21 Operator Overloading 421

Notice the following:

n The operator is public All operators must be public

n The operator is static All operators must be static Operators are never polymorphic and cannot use the virtual, abstract, override, or sealed modifier

n A binary operator (such as the + operator, shown earlier) has two explicit arguments,

and a unary operator has one explicit argument (C++ programmers should note that

operators never have a hidden this parameter )

Tip When declaring highly stylized functionality (such as operators), it is useful to adopt a

naming convention for the parameters For example, developers often use lhs and rhs (acronyms

for left-hand side and right-hand side, respectively) for binary operators

When you use the + operator on two expressions of type Hour, the C# compiler

automatically converts your code to a call to your operator+ method The C# compiler

converts the code

Hour Example(Hour a, Hour b)

Note, however, that this syntax is pseudocode and not valid C# You can use a binary

operator only in its standard infix notation (with the symbol between the operands)

There is one final rule that you must follow when declaring an operator (otherwise, your code will not compile): at least one of the parameters must always be of the containing type In

the preceding operator+ example for the Hour class, one of the parameters, a or b, must be

an Hour object In this example, both parameters are Hour objects However, there could be

Trang 3

times when you want to define additional implementations of operator+ that add, for ample, an integer (a number of hours) to an Hour object—the first parameter could be Hour,

ex-and the second parameter could be the integer This rule makes it easier for the compiler to know where to look when trying to resolve an operator invocation, and it also ensures that you can’t change the meaning of the built-in operators

Creating Symmetric Operators

In the preceding section, you saw how to declare a binary + operator to add together two

instances of type Hour The Hour structure also has a constructor that creates an Hour from

an int This means that you can add together an Hour and an int—you just have to first use the Hour constructor to convert the int to an Hour For example:

Hour a = ;

int b = ;

Hour sum = a + new Hour(b);

This is certainly valid code, but it is not as clear or concise as adding together an Hour and an int directly, like this:

following code shows the recommended approach:

Trang 4

Chapter 21 Operator Overloading 423

Notice that all the second version of the operator does is construct an Hour from its int

argument and then call the first version In this way, the real logic behind the operator is

held in a single place The point is that the extra operator + simply makes existing

function-ality easier to use Also, notice that you should not provide many different versions of this operator, each with a different second parameter type—instead, cater to the common and meaningful cases only, and let the user of the class take any additional steps if an unusual case is required

This operator+ declares how to add together an Hour as the left-hand operand and an int

as the right-hand operand It does not declare how to add together an int as the left-hand operand and an Hour as the right-hand operand:

int a = ;

Hour b = ;

Hour sum = a + b; // compile-time error

This is counterintuitive If you can write the expression a + b, you expect to also be able to write b + a Therefore, you should provide another overload of operator+:

Note C++ programmers should notice that you must provide the overload yourself The

compiler won’t write the overload for you or silently swap the sequence of the two operands to find a matching operator

Trang 5

Operators and Language Interoperability

Not all languages that execute using the common language runtime (CLR) support

or understand operator overloading If you are creating classes that you want to be able to use from other languages, if you overload an operator, you should provide an alternative mechanism that supports the same functionality For example, suppose you

implement operator+ for the Hour structure:

public static Hour operator +(Hour lhs, int rhs)

{

}

If you need to be able to use your class from a Visual Basic application, you should also

provide an Add method that achieves the same thing:

public static Hour Add(Hour lhs, int rhs)

{

}

Understanding Compound Assignment Evaluation

A compound assignment operator (such as +=) is always evaluated in terms of its associated operator (such as +) In other words, the statement

a because that’s the same as b = b + a Although the addition is valid, the assignment is not, because there is no way to assign an Hour to the built-in int type

Trang 6

Chapter 21 Operator Overloading 425

Declaring Increment and Decrement Operators

C# allows you to declare your own version of the increment (++) and decrement (––)

operators The usual rules apply when declaring these operators: they must be public, they must be static, and they must be unary (they can only take a single parameter) Here is the

increment operator for the Hour structure:

sions The result of a postfix expression is the value of the operand before the expression

takes place In other words, the compiler effectively converts the code

Hour now = new Hour(9);

Hour postfix = now++;

to this:

Hour now = new Hour(9);

Hour postfix = now;

now = Hour.operator ++(now); // pseudocode, not valid C#

The result of a prefix expression is the return value of the operator The C# compiler

effectively converts the code

Hour now = new Hour(9);

Hour prefix = ++now;

to this:

Hour now = new Hour(9);

now = Hour.operator ++(now); // pseudocode, not valid C#

Hour prefix = now;

This equivalence means that the return type of the increment and decrement operators must

be the same as the parameter type

Trang 7

Comparing Operators in Structures and Classes

Be aware that the implementation of the increment operator in the Hour structure works only because Hour is a structure If you change Hour into a class but leave the implementa-

tion of its increment operator unchanged, you will find that the postfix translation won’t give the correct answer If you remember that a class is a reference type and revisit the compiler translations explained earlier, you can see why this occurs:

Hour now = new Hour(9);

Hour postfix = now;

now = Hour.operator ++(now); // pseudocode, not valid C#

If Hour is a class, the assignment statement postfix = now makes the variable postfix refer to the same object as now Updating now automatically updates postfix! If Hour is a structure, the assignment statement makes a copy of now in postfix, and any changes to now leave postfix unchanged, which is what we want

The correct implementation of the increment operator when Hour is a class is as follows:

Notice that operator ++ now creates a new object based on the data in the original The data

in the new object is incremented, but the data in the original is left unchanged Although this works, the compiler translation of the increment operator results in a new object being creat-

ed each time it is used This can be expensive in terms of memory use and garbage collection overhead Therefore, it is recommended that you limit operator overloads when you define types This recommendation applies to all operators, and not just to the increment operator

Defining Operator Pairs

Some operators naturally come in pairs For example, if you can compare two Hour values

by using the != operator, you would expect to be able to also compare two Hour values by using the == operator The C# compiler enforces this very reasonable expectation by insist- ing that if you define either operator == or operator !=, you must define them both This

Trang 8

Chapter 21 Operator Overloading 427

neither-or-both rule also applies to the < and > operators and the <= and >= operators

The C# compiler does not write any of these operator partners for you You must write them

all explicitly yourself, regardless of how obvious they might seem Here are the == and != operators for the Hour structure:

Note If you define operator == and operator != in a class, you should also override the Equals and GetHashCode methods inherited from System.Object (or System.ValueType if you are creating

a structure) The Equals method should exhibit exactly the same behavior as operator == (You should define one in terms of the other ) The GetHashCode method is used by other classes in the

Microsoft NET Framework (When you use an object as a key in a hash table, for example, the

GetHashCode method is called on the object to help calculate a hash value For more

informa-tion, see the NET Framework Reference documentation supplied with Visual Studio 2010 ) All this method needs to do is return a distinguishing integer value (Don’t return the same integer from

the GetHashCode method of all your objects, however, because this will nullify the effectiveness

of the hashing algorithms )

Implementing Operators

In the following exercise, you will develop a class that simulates complex numbers

A complex number has two elements: a real component and an imaginary component

Typically, a complex number is represented in the form (x + yi), where x is the real nent and yi is the imaginary component The values of x and y are regular integers, and i

Trang 9

compo-represents the square root of –1 (hence the reason why yi is imaginary) Despite their rather

obscure and theoretical feel, complex numbers have a large number of uses in the fields of electronics, applied mathematics, physics, and many aspects of engineering

Note The NET Framework 4 0 now includes a type called Complex in the System.Numerics

namespace that implements complex numbers, so there is no real need to define your own

implementation any more However, it is still instructive to see how to implement some of the common operators for this type

You will implement complex numbers as a pair of integers that represent the coefficients

x and y for the real and imaginary elements You will also implement the operands necessary for performing simple arithmetic using complex numbers The following table summarizes how to perform the four primary arithmetic operations on a pair of complex numbers,

(a + bi) and (c + di)

Operation Calculation

(a + bi) + (c + di) ((a + c) + (b + d)i)

(a + bi) – (c + di) ((a – c) + (b – d)i)

(a + bi) * (c + di) (( a * c – b * d) + (b * c + a * d)i)

(a + bi) / (c + di) ((( a * c + b * d) / ( c * c + d * d)) + ( b * c - a * d) / ( c * c + d * d))i)

Create the Complex class, and implement the arithmetic operators

1 Start Microsoft Visual Studio 2010 if it is not already running

2 Open the ComplexNumbers project, located in the \Microsoft Press\Visual CSharp Step

By Step\Chapter 21\ComplexNumbers folder in your Documents folder This is a console application that you will use to build and test your code The Program cs file contains

the familiar DoWork method

3 On the Project menu, click Add Class In the Add New Item – Complex Numbers dialog

box, type Complex cs in the Name text box and then click Add

Visual Studio creates the Complex class and opens the Complex cs file in the Code and Text Editor window

4 Add the automatic integer properties Real and Imaginary to the Complex class, as

shown next in bold You will use these two properties to hold the real and imaginary components of a complex number

class Complex

{

public int Real { get; set; }

public int Imaginary { get; set; }

}

Trang 10

Chapter 21 Operator Overloading 429 5 Add the constructor shown next in bold to the Complex class This constructor takes

two int parameters and uses them to populate the Real and Imaginary properties

6 Override the ToString method as shown next in bold This method returns a string

representing the complex number in the form (x + yi)

7 Add the overloaded + operator shown next in bold to the Complex class This is the

binary addition operator It takes two Complex objects and adds them together by

performing the calculation shown in the table at the start of the exercise The operator

returns a new Complex object containing the results of this calculation

8 Add the overloaded – operator to the Complex class This operator follows the same

form as the overloaded + operator

9 Implement the * operator and / operator These two operators follow the same form

as the previous two operators, although the calculations are a little more complicated

Trang 11

(The calculation for the / operator has been broken down into two steps to avoid lengthy lines of code )

return new Complex(lhs.Real * rhs.Real + lhs.Imaginary * rhs.Real,

lhs.Imaginary * rhs.Imaginary + lhs.Real * rhs.Imaginary); }

public static Complex operator /(Complex lhs, Complex rhs)

{

int realElement = (lhs.Real * rhs.Real + lhs.Imaginary * rhs.Imaginary) / (rhs.Real * rhs.Real + rhs.Imaginary * rhs.Imaginary); int imaginaryElement = (lhs.Imaginary * rhs.Real - lhs.Real * rhs.Imaginary) / (rhs.Real * rhs.Real + rhs.Imaginary * rhs.Imaginary); return new Complex(realElement, imaginaryElement);

}

}

10 Display the Program cs file in the Code and Text Editor window Add the following

statements shown in bold to the DoWork method of the Program class:

static void DoWork()

{

Complex first = new Complex(10, 4);

Complex second = new Complex(5, 2);

Console.WriteLine("first is {0}", first);

Console.WriteLine("second is {0}", second);

Complex temp = first + second;

Console.WriteLine("Add: result is {0}", temp);

temp = first - second;

Console.WriteLine("Subtract: result is {0}", temp);

temp = first * second;

Console.WriteLine("Multiply: result is {0}", temp);

temp = first / second;

Console.WriteLine("Divide: result is {0}", temp);

}

This code creates two Complex objects that represent the complex values (10 + 4i) and

(5 + 2i) The code displays them, and then tests each of the operators you have just defined, displaying the results in each case

11 On the Debug menu, click Start Without Debugging

Verify that the application displays the results shown in the following image

Trang 12

Chapter 21 Operator Overloading 431

12 Close the application, and return to the Visual Studio 2010 programming environment

You have now created a type that models complex numbers and supports basic arithmetic

operations In the next exercise, you will extend the Complex class and provide the ity operators, == and != Remember that if you implement these operators you should also override the Equals and GetHashCode methods that the class inherits from the Object type

equal-Implement the equality operators

1 In Visual Studio 2010, display the Complex cs file in the Code and Text Editor window

2 Add the == and != operators to the Complex class as shown next in bold Notice that

these operators both make use of the Equal method The Equal method compares an instance of a class against another instance specified as an argument It returns true if they are equal and false otherwise

3 On the Build menu, click Rebuild Solution

The Error List window displays the following warning messages:

'ComplexNumbers.Complex' defines operator == or operator != but does not override Object.GetHashCode()

'ComplexNumbers.Complex' defines operator == or operator != but does not override Object.Equals(object o)

If you define the != and == operators, you should also override the Equal and

GetHashCode methods inherited from SystemObject

Trang 13

Note If the Error List window is not displayed, on the View menu, click Error List

4 Override the Equals method in the Complex class as shown next in bold:

Complex compare = (Complex)obj;

return (this.Real == compare.Real) &&

Important It is tempting to write the Equals method like this:

public override bool Equals(Object obj) {

Complex compare = obj As Complex;

if (compare != null) {

return (this.Real == compare.Real) &&

(this.Imaginary == compare.Imaginary);

} else { return false;

} } However, the expression compare != null invokes the != operator of the Complex class,

which calls the Equals method again, resulting in an infinitely recursive loop

5 Override the GetHashCode method This implementation simply calls the method

inherited from the Object class, but you can provide your own mechanism to generate

a hash code for an object if you prefer

Trang 14

Chapter 21 Operator Overloading 433

6 On the Build menu, click Rebuild Solution

Verify that the solution now builds without reporting any warnings

7 Display the Program cs file in the Code and Text Editor window Add the following code

to the end of the DoWork method:

static void DoWork()

8 On the Debug menu, click Start Without Debugging Verify that the final two messages

displayed are these:

Comparison: temp != first

Comparison: temp == temp

9 Close the application, and return to Visual Studio 2010

Trang 15

Understanding Conversion Operators

Sometimes you need to convert an expression of one type to another For example, the

following method is declared with a single double parameter:

You might reasonably expect that only values of type double could be used as

argu-ments when calling MyDoubleMethod, but this is not so The C# compiler also allows MyDoubleMethod to be called with an argument whose type is not double, but only if that value can be converted to a double For example, you can provide an int argument In that case, the compiler generates code that converts the argument from an int to a double when

the method is called

Providing Built-in Conversions

The built-in types have some built-in conversions For example, as mentioned previously, an

int can be implicitly converted to a double An implicit conversion requires no special syntax

and never throws an exception:

Example.MyDoubleMethod(42); // implicit int-to-double conversion

An implicit conversion is sometimes called a widening conversion because the result is wider

than the original value—it contains at least as much information as the original value, and nothing is lost

On the other hand, a double cannot be implicitly converted to an int:

Example.MyIntMethod(42.0); // compile-time error

When you convert a double to an int, you run the risk of losing information, so the

conver-sion will not be performed automatically (Consider what would happen if the argument to

MyIntMethod were 42 5—how should this be converted?) A double can be converted to an int, but the conversion requires an explicit notation (a cast):

Example.MyIntMethod((int)42.0);

Trang 16

Chapter 21 Operator Overloading 435

An explicit conversion is sometimes called a narrowing conversion because the result is narrower than the original value (that is, it can contain less information) and can throw an OverflowException C# allows you to provide conversion operators for your own user-defined

types to control whether it is sensible to convert values to other types and whether these conversions are implicit or explicit

Implementing User-Defined Conversion Operators

The syntax for declaring a user-defined conversion operator is similar to that for declaring an

overloaded operator A conversion operator must be public and must also be static Here’s a conversion operator that allows an Hour object to be implicitly converted to an int:

When declaring your own conversion operators, you must specify whether they are implicit

conversion operators or explicit conversion operators You do this by using the implicit and explicit keywords For example, the Hour to int conversion operator mentioned earlier is

implicit, meaning that the C# compiler can use it implicitly (without requiring a cast):

class Example

{

public static void MyOtherMethod(int parameter) { }

public static void Main()

{

Hour lunch = new Hour(12);

Example.MyOtherMethod(lunch); // implicit Hour to int conversion

}

}

If the conversion operator had been declared explicit, the preceding example would not have

compiled, because an explicit conversion operator requires an explicit cast:

Example.MyOtherMethod((int)lunch); // explicit Hour to int conversion

Trang 17

When should you declare a conversion operator as explicit or implicit? If a conversion is always safe, does not run the risk of losing information, and cannot throw an exception, it

can be defined as an implicit conversion Otherwise, it should be declared as an explicit version Converting from an Hour to an int is always safe—every Hour has a corresponding int value—so it makes sense for it to be implicit An operator that converts a string to an Hour should be explicit because not all strings represent valid Hours (The string “7” is fine, but how would you convert the string “Hello, World” to an Hour?)

con-Creating Symmetric Operators, Revisited

Conversion operators provide you with an alternative way to resolve the problem of providing symmetric operators For example, instead of providing three versions of

operator+ (Hour + Hour, Hour + int, and int + Hour) for the Hour structure, as shown lier, you can provide a single version of operator+ (that takes two Hour parameters) and an implicit int to Hour conversion, like this:

If you add an Hour to an int (in either order), the C# compiler automatically converts the int

to an Hour and then calls operator+ with two Hour arguments:

void Example(Hour a, int b)

{

Hour eg1 = a + b; // b converted to an Hour

Hour eg2 = b + a; // b converted to an Hour

}

Trang 18

Chapter 21 Operator Overloading 437Writing Conversion Operators

In the following exercise, you will add further operators to the Complex class You will start

by writing a pair of conversion operators that convert between the int type and the Complex type Converting an int to a Complex object is always a safe process and never loses informa- tion (because an int is really just a Complex number without an imaginary element) So you

will implement this as an implicit conversion operator However, the converse is not true; to

convert a Complex object into an int, you have to discard the imaginary element So you will

implement this conversion operator as explicit

Implement the conversion operators

1 Return to Visual Studio 2010 and display the Complex cs file in the Code and Text Editor

window Add the constructor shown next in bold to the Complex class This constructor takes a single int parameter which it uses to initialize the Real property The imaginary

2 Add the following implicit conversion operator to the Complex class This operator

converts from an int to a Complex object by returning a new instance of the Complex

class by using the constructor you created in the previous step

Trang 19

3 Add the explicit conversion operator shown next to the Complex class This operator

takes a Complex object and returns the value of the Real property This conversion

discards the imaginary element of the complex number

4 Display the Program cs file in the Code and Text Editor window Add the following code

to the end of the DoWork method:

static void DoWork()

of the Complex class The statement that adds 2 to the temp variable converts the int value 2 into a Complex object and then uses the + operator of the Complex class

5 Add the following statements to end of the DoWork method:

static void DoWork()

{

int tempInt = temp;

Console.WriteLine("Int value after conversion: tempInt = {0}", tempInt);

}

The first statement attempts to assign a Complex object to an int variable

Trang 20

Chapter 21 Operator Overloading 439

6 On the Build menu, click Rebuild Solution

The solution fails to build, and the compiler reports the following error in the Error List

window:

Cannot implicitly convert type 'ComplexNumbers.Complex' to 'int' An explicit

conversion exists (are you missing a cast?)

The operator that converts from a Complex object to an int is an explicit conversion

operator, so you must specify a cast

7 Modify the statement that attempts to store a Complex value in an int variable to use a

cast, like this:

int tempInt = (int)temp;

8 On the Debug menu, click Start Without Debugging Verify that the solution now builds,

and that the final four statements output are these:

Current value of temp is (2 + 0i)

Comparison after conversion: temp == 2

Value after adding 2: temp = (4 + 0i)

Int value after conversion: tempInt = 4

9 Close the application, and return to Visual Studio 2010

In this chapter, you learned how to overload operators and provide functionality specific to a class or structure You implemented a number of common arithmetic operators, and you also created operators that enable you to compare instances of a class Finally, you learned how

to create implicit and explicit conversion operators

n If you want to continue to the next chapter

Keep Visual Studio 2010 running, and turn to Chapter 22

n If you want to exit Visual Studio 2010 now

On the File menu, click Exit If you see a Save dialog box, click Yes and save the project

Trang 21

Chapter 21 Quick Reference

Implement an operator Write the keywords public and static, followed by the return type,

followed by the operator keyword, followed by the operator symbol

being declared, followed by the appropriate parameters between theses Implement the logic for the operator in the body of the method For example:

paren-class Complex {

or explicit, followed by the operator keyword, followed by the type

be-ing converted to, followed by the type bebe-ing converted from as a sbe-ingle parameter between parentheses For example:

class Complex {

Trang 22

Microsoft Visual C# 2010 Step by Step

Trang 24

443

Chapter 22

Introducing Windows Presentation Foundation

After completing this chapter, you will be able to:

n Create Microsoft Windows Presentation Foundation (WPF) applications

n Use common WPF controls such as labels, text boxes, and buttons

n Define styles for WPF controls

n Change the properties of WPF forms and controls at design time and through code at run time

n Handle events exposed by WPF forms and controls

Now that you have completed the exercises and examined the examples in the first three parts of this book, you should be well versed in the C# language You have learned how to write programs and create components by using Microsoft C#, and you should understand many of the finer points of the language, such as extension methods, lambda expressions, and the distinction between value and reference types You now have the essential lan-guage skills, and in Part IV you will expand upon them and use C# to take advantage of the graphical user interface (GUI) libraries provided as part of the Microsoft NET Framework In

particular, you will see how to use the objects in the System.Windows namespace to create

WPF applications

In this chapter, you learn how to build a basic WPF application by using the common

components that are a feature of most GUI applications You see how to set the properties of

WPF forms and controls by using the Design View and Properties windows, and also by using

Extensible Application Markup Language, or XAML You also learn how to use WPF styles to build user interfaces that can be easily adapted to conform to your organization’s presenta-tion standards Finally, you learn how to intercept and handle some of the events that WPF forms and controls expose

Trang 25

concentrat-later chapters, you will provide menus and learn how to implement validation to ensure that the data that is entered makes sense The following graphic shows what the application will look like after you have completed it (You can see the completed version by building and running the BellRingers project in the \Microsoft Press\Visual CSharp Step By Step\Chapter 22\BellRingers - Complete\ folder in your Documents folder )

Building the WPF Application

In this exercise, you’ll start building the Middleshire Bell Ringers Association application by creating a new project, laying out the form, and adding controls to the form You have been using existing WPF applications in Microsoft Visual Studio 2010 in previous chapters, so much

of the first couple of exercises will be a review for you

Create the Middleshire Bell Ringers Association project

1 Start Visual Studio 2010 if it is not already running

2 If you are using Visual Studio 2010 Standard or Visual Studio 2010 Professional, perform

the following operations to create a new WPF application:

2 1 On the File menu, point to New, and then click Project

The New Project dialog box opens

2 2 In the left pane, expand Installed Templates (if it is not already expanded) expand

Visual C#, and then click Windows

2 3 In the middle pane, click the WPF Application icon

Ngày đăng: 05/07/2014, 16:20

TỪ KHÓA LIÊN QUAN