- C#入門經典(第7版):C# 6.0 & Visual Studio 2015(.NET開發經典名著)
- (美)Beijamin Perkins Jacob Vibe Hammer Jon D. Reid
- 3816字
- 2021-04-02 21:18:33
3.4 表達式
C#包含許多執行這類處理的運算符。把變量和字面值(在使用運算符時,它們都稱為操作數)與運算符組合起來,就可以創建表達式,它是計算的基本構件。
運算符范圍廣泛,有簡單的,也有非常復雜的,其中一些可能只在數學應用程序中使用。簡單的操作包括所有的基本數學操作,例如+運算符是把兩個操作數加在一起,而復雜的操作包括通過變量內容的二進制表示來處理它們。還有專門用于處理布爾值的邏輯運算符,以及賦值運算符,如=運算符。
本章主要介紹數學和賦值運算符,而邏輯運算符將在第4章中介紹,因為第4章主要論述控制程序流程的布爾邏輯。
運算符大致分為如下3類:
● 一元運算符,處理一個操作數
● 二元運算符,處理兩個操作數
● 三元運算符,處理三個操作數
大多數運算符都是二元運算符,只有幾個一元運算符和一個三元運算符,即條件運算符(條件運算符是一個邏輯運算符,詳見第4章)。下面首先介紹數學運算符,它包括一元運算符和二元運算符。
3.4.1 數學運算符
有5個簡單的數學運算符,其中兩個(+和-)有二元和一元兩種形式。表3-6列出了這些運算符,并用一個簡短示例來說明它們的用法,以及使用簡單的數值類型(整數和浮點數)時它們的結果。
表3-6 簡單的數學運算符

+(一元)運算符有點古怪,因為它對結果沒有影響。它不會把值變成正的:如果var2是-1,則+var2仍是-1。但這是一個得到普遍認可的運算符,所以也把它包含進來。這個運算符最有用的方面是,可以定制它的操作,本書在后面探討運算符的重載時會介紹它。
上面的示例都使用簡單的數值類型,因為使用其他簡單類型,結果可能不太清晰。例如把兩個布爾值加在一起,會得到什么結果?因此,如果對bool變量使用+(或其他數學運算符),編譯器會報錯。char變量的相加也會有點讓人摸不著頭腦。記住,char變量實際上存儲的是數字,所以把兩個char變量加在一起也會得到一個數字(其類型為int)。這是一個隱式轉換示例,稍后將詳細介紹這個主題和顯式轉換,因為它也可以應用到var1、var2和var3是混合類型的情況。
二元運算符+在用于字符串類型變量時也是有意義的。此時,它的作用如表3-7所示。
表3-7 字符串連接運算符

但其他數學運算符不能用于處理字符串。
這里應介紹的另兩個運算符是遞增和遞減運算符,它們都是一元運算符,可通過兩種方式加以使用:放在操作數的前面或后面。簡單表達式的結果如表3-8所示。
表3-8 簡單表達式的結果

這些運算符改變存儲在操作數中的值。
● ++總是使操作數加1
● - - 總是使操作數減1
var1中存儲的結果有區別,其原因是運算符的位置決定了它什么時候發揮作用。把運算符放在操作數的前面,則操作數是在進行任何其他計算前受到運算符的影響;而如果把運算符放在操作數的后面,則操作數是在完成表達式的計算后受到運算符的影響。
再看一個示例。考慮以下代碼:
int var1, var2 = 5, var3 = 6; var1 = var2++ * --var3;
要把什么值賦予var1?在計算表達式前,var3前面的運算符--會起作用,把它的值從6改為5。可以忽略var2后面的++運算符,因為它是在計算完成后才發揮作用,所以var1的結果是5與5的乘積,即25。
許多情況下,這些簡單的一元運算符使用起來非常方便,它們實際上是下述表達式的簡寫形式:
var1 = var1 + 1;
這類表達式有許多用途,特別適于在循環中使用,這將在第4章講述。下面的示例說明如何使用數學運算符,并介紹另外兩個有用的概念。代碼提示用戶鍵入一個字符串和兩個數字,然后顯示計算結果。
試一試:用數學運算符處理變量:Ch03Ex02\Program.cs
(1)在目錄C:\BegVCSharp\Chapter03下創建一個新的控制臺應用程序Ch03Ex02。
(2)在Program.cs中添加如下代碼:
static void Main(string[] args)
{
double firstNumber, secondNumber;
string userName;
Console.WriteLine("Enter your name:");
userName = Console.ReadLine();
Console.WriteLine($"Welcome {userName}! ");
Console.WriteLine("Now give me a number:");
firstNumber = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Now give me another number:");
secondNumber = Convert.ToDouble(Console.ReadLine());
Console.WriteLine($"The sum of {firstNumber} and {secondNumber} is " +
$"{firstNumber + secondNumber}.");
Console.WriteLine($"The result of subtracting {secondNumber} from " +
$"{firstNumber} is {firstNumber - secondNumber}.");
Console.WriteLine($"The product of {firstNumber} and {secondNumber} " +
$"is {firstNumber * secondNumber}.");
Console.WriteLine($"The result of dividing {firstNumber} by " +
$"{secondNumber} is {firstNumber / secondNumber}.");
Console.WriteLine($"The remainder after dividing {firstNumber} by " +
$"{secondNumber} is {firstNumber % secondNumber}.");
Console.ReadKey();
}
(3)執行代碼,結果如圖3-2所示。

圖3-2
(4)輸入名稱,按下回車鍵,如圖3-3所示。

圖3-3
(5)輸入一個數字,按下回車鍵,再輸入另一個數字,按下回車鍵,結果如圖3-4所示。

圖3-4
示例說明
除了演示數學運算符外,這段代碼還引入了兩個重要概念,在以后的示例中將多次用到這些概念:
● 用戶輸入
● 類型轉換
用戶輸入使用與前面Console.WriteLine()命令類似的語法。但這里使用Console.ReadLine()。這個命令提示用戶輸入信息,并把它們存儲在string變量中:
string userName; Console.WriteLine("Enter your name:"); userName = Console.ReadLine(); Console.WriteLine($"Welcome {userName}! ");
這段代碼直接將已賦值變量userName的內容寫到屏幕上。
這個示例還讀取了兩個數字。這有些復雜,因為Console.ReadLine()命令生成一個字符串,而我們希望得到一個數字,所以這就引入了類型轉換的問題。第5章將詳細討論類型轉換,下面首先分析本例使用的代碼。
首先聲明要存儲數字輸入的變量:
double firstNumber, secondNumber;
接著給出提示,對Console.ReadLine()得到的字符串使用命令Convert.ToDouble(),把字符串轉換為double類型,把這個數值賦給前面聲明的變量firstNumber:
Console.WriteLine("Now give me a number:"); firstNumber = Convert.ToDouble(Console.ReadLine());
這個語法相當簡單,其他許多轉換也用類似的方式進行。
其余代碼按同樣方式獲取第二個數:
Console.WriteLine("Now give me another number:"); secondNumber = Convert.ToDouble(Console.ReadLine());
然后輸出兩個數字加、減、乘、除的結果,并用余數運算符(%)顯示除操作的余數:
Console.WriteLine($"The sum of {firstNumber} and {secondNumber} is " + $"{firstNumber + secondNumber}."); Console.WriteLine($"The result of subtracting {secondNumber} from " + $"{firstNumber} is {firstNumber - secondNumber}."); Console.WriteLine($"The product of {firstNumber} and {secondNumber} " + $"is {firstNumber * secondNumber}."); Console.WriteLine($"The result of dividing {firstNumber} by " + $"{secondNumber} is {firstNumber / secondNumber}."); Console.WriteLine($"The remainder after dividing {firstNumber} by " + $"{secondNumber} is {firstNumber % secondNumber}.");
注意,我們提供了表達式firstNumber + secondNumber等,作為Console.WriteLine()語句的一個參數,而沒有使用中間變量:
Console.WriteLine($"The sum of {firstNumber} and {secondNumber} is " + $"{firstNumber + secondNumber}.");
這種語法可以提高代碼的可讀性,并減少需要編寫的代碼量。
3.4.2 賦值運算符
我們迄今一直在使用簡單的=賦值運算符,其實還有其他賦值運算符,而且它們都很有用。除了=運算符外,其他賦值運算符都以類似方式工作。與=一樣,它們都是根據運算符和右邊的操作數,把一個值賦給左邊的變量。
表3-9列出了這些運算符及其說明。
表3-9 賦值運算符

可以看出,這些運算符把var1也包括在計算過程中,下面的代碼:
var1 += var2;
與下面的代碼結果相同。
var1 = var1 + var2;
注意:與+運算符一樣,+=運算符也可以用于字符串。
使用這些運算符,特別是在使用長變量名時,可使代碼更便于閱讀。
3.4.3 運算符的優先級
在計算表達式時,會按順序處理每個運算符。但這并不意味著必須從左至右地運用這些運算符。例如,考慮下面的代碼:
var1 = var2 + var3;
其中+運算符就是在=運算符之前進行計算的。在其他一些情況下,運算符的優先級并沒有這么明顯,例如:
var1 = var2 + var3 * var4;
其中*運算符首先計算,其后是+運算符,最后是=運算符,這是標準的數學運算順序,其結果與我們在紙上進行算術運算的結果相同。
像這樣的計算,可以使用括號控制運算符的優先級,例如:
var1 = (var2 + var3) * var4;
首先計算括號中的內容,即+運算符在*運算符之前計算。
對于前面介紹的運算符,其優先級如表3-10所示,優先級相同的運算符(如*和/)按照從左至右的順序計算。
表3-10 運算符的優先級

注意:如上所述,括號可用于重寫優先級順序。另外,++和- -用作后綴運算符時,在概念上其優先級最低,如上表所示。它們不對賦值表達式的結果產生影響,所以可以認為它們的優先級比所有其他運算符都高。但是,它們會在計算表達式后改變操作數的值,所以認為它們的優先級如表3-10所示會十分方便。
3.4.4 名稱空間
在繼續學習前,應花一定的時間了解一個比較重要的主題—— 名稱空間。它們是.NET中提供應用程序代碼容器的方式,這樣就可以唯一地標識代碼及其內容。名稱空間也用作.NET Framework中給項分類的一種方式。大多數項都是類型定義,例如,本章描述的簡單類型(System.Int32等)。
默認情況下,C#代碼包含在全局名稱空間中。這意味著對于包含在這段代碼中的項,全局名稱空間中的其他代碼只要通過名稱進行引用,就可以訪問它們。可使用namespace關鍵字為花括號中的代碼塊顯式定義名稱空間。如果在該名稱空間代碼的外部使用名稱空間中的名稱,就必須寫出該名稱空間中的限定名稱。
限定名稱包括它所有的分層信息。這意味著,如果一個名稱空間中的代碼需要使用在另一個名稱空間中定義的名稱,就必須包括對該名稱空間的引用。限定名稱在不同的名稱空間級別之間使用句點字符(.),如下所示:
namespace LevelOne { // code in LevelOne namespace // name "NameOne" defined } // code in global namespace
這段代碼定義了一個名稱空間LevelOne,以及該名稱空間中的一個名稱NameOne(注意這里在應該定義名稱空間的地方添加了一個注釋,而沒有列出實際代碼,這是為了使我們的討論更具普遍性)。在名稱空間LevelOne中編寫的代碼可以直接使用NameOne來引用該名稱,但全局名稱空間中的代碼必須使用限定名稱LevelOne.NameOne來引用這個名稱。
需要注意特別重要的一點:using語句本身不能訪問另一個名稱空間中的名稱。除非名稱空間中的代碼以某種方式鏈接到項目上,或者代碼是在該項目的源文件中定義的,或者是在鏈接到該項目的其他代碼中定義的,否則就不能訪問其中包含的名稱。另外,如果包含名稱空間的代碼鏈接到項目上,那么無論是否使用using,都可以訪問其中包含的名稱。using語句便于我們訪問這些名稱,減少代碼量,以及提高可讀性。
回頭分析本章開頭的ConsoleApplication1中的代碼,會看到下面這些被應用到名稱空間上的代碼:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { ... }
以using關鍵字開頭的5行代碼聲明在這段C#代碼中使用System、System.Collections.Generic、System.Linq、System.Text和System.Threading.Tasks名稱空間,它們可以在該文件的所有名稱空間中訪問,不必進行限定。System名稱空間是.NET Framework應用程序的根名稱空間,包含控制臺應用程序需要的所有基本功能。其他4個名稱空間常用于控制臺應用程序,所以該程序包含了它們。最后,為應用程序代碼本身聲明一個名稱空間ConsoleApplication1。
C# 6新增了using static關鍵字。這個關鍵字允許把靜態成員直接包含到C#程序的作用域中。例如,本章的兩個示例都使用了System.Console靜態類中的System.Console.WriteLine()方法。注意,在這些例子中,應包括Console類和WriteLine()方法。把using static System.Console添加到名稱空間列表中時,訪問WriteLine()方法就不再需要在前面加上靜態類名。
之后需要System .Console靜態類的代碼示例就包括using static System.Console關鍵字。
- Leap Motion Development Essentials
- 基于差分進化的優化方法及應用
- Visual Basic程序設計習題解答與上機指導
- WebRTC技術詳解:從0到1構建多人視頻會議系統
- Python入門很輕松(微課超值版)
- Web前端開發最佳實踐
- Python物理建模初學者指南(第2版)
- Mastering OpenStack
- Python高性能編程(第2版)
- 透視C#核心技術:系統架構及移動端開發
- Manage Your SAP Projects with SAP Activate
- 第五空間戰略:大國間的網絡博弈
- Game Programming using Qt 5 Beginner's Guide
- JSP編程教程
- Computer Vision with Python 3