1、使用 for 循环和 continue 语句,创建一个代码片段,将 1 到 10 之间的偶数输出到控制台。
以下是满足要求的 C# 代码片段:
using System;
public class Program
{
static void Main()
{
for (int i = 1; i <= 10; i++)
{
if (i % 2 != 0)
{
continue;
}
Console.WriteLine(i);
}
}
}
在上述代码中,使用 循环遍历 1 到 10 的数字。对于每个数字,使用
for 语句检查是否为奇数(即
if ),如果是奇数,则执行
i % 2 != 0 语句跳过当前循环,继续下一次循环;如果是偶数,则使用
continue 方法将该数字输出到控制台。
Console.WriteLine
2、根据代码块定义和正确缩进技术,使以下代码片段更具可读性:int count = 0; for (int j = 0; j < 2; j++) { count = j; for (int k = 0; k < 3; k++) count++; Console.WriteLine(“count = ” + count); }
int count = 0;
for (int j = 0; j < 2; j++) {
count = j;
for (int k = 0; k < 3; k++) {
count++;
}
Console.WriteLine("count = " + count);
}
3、给定初始变量声明和赋值:int a = 1; int b = 1; int c = 1; 计算以下表达式的值:(((c++ + –a) * b) != 2) && true)
首先计算表达式中各部分的值。
先看 :
c++ + --a
– 是先使用
c++ 的值再自增,此时
c 的值为 1;
c
– 是先自减再使用
--a 的值,
a 自减后为 0;
a
– 所以 的结果是
c++ + --a 。
1 + 0 = 1
接着 即
(c++ + --a) * b ,
1 * 1 = 1
不等于
1 ,所以
2 的结果为
((c++ + --a) * b) != 2 。
true
与
true 进行
true 运算,结果为
&& 。
true
因此,该表达式的值为 。
true
4、以合理的方式绘制一个抽象层次结构,关联以下所有类别:苹果、香蕉、牛肉、饮料、奶酪、可消费物、乳制品、食物、水果、青豆、肉类、牛奶、猪肉、菠菜、蔬菜。并指出你在绘制过程中遇到的任何挑战。
抽象层次结构
可消费物(顶层) 食物
水果 苹果 香蕉 蔬菜 青豆 菠菜 肉类 牛肉 猪肉 乳制品 奶酪 牛奶 饮料
挑战在于 :确定每个类别之间的准确关系,部分类别界限模糊,例如某些可食用物品可能同时符合多种分类标准。
5、以下代码有什么问题?指出违背面向对象编程惯例的地方,无论C#编译器是否会报错。首先是使用“get”/“set”方法的示例:public class Building { private string address; public int numberOfFloors; void GetnumberOfFloors() { return numberOfFloors; } private void SetNoOfFloors(float n) { NumberOfFloors = n; } } 其次是使用属性的示例:public class Building { private string address; public int numberOfFloors public long NumberOfFloors { int get { return numberOfFloors; } private set { numberOfFloors = value; } } }
使用“get”/“set”方法的代码存在以下问题:
方法声明为
GetnumberOfFloors 却有返回值,应将返回类型改为
void ;
int 方法为
SetNoOfFloors ,外部无法调用,应改为
private ;
public 未定义,应改为
NumberOfFloors ;
numberOfFloors 是
numberOfFloors 类型,而传入的参数
int 是
n 类型,可能会导致数据丢失。
float
使用属性的代码存在以下问题:
语句结尾缺少分号;
public int numberOfFloors 属性的
NumberOfFloors 访问器声明返回
get ,但属性类型是
int ,类型不匹配。
long
6、如果类FeatureFilm定义了以下方法:public void Update(Actor a, string title); public void Update(Actor a, Actor b, string title); public void Update(string topic, string title); 以下哪些额外的方法头会被编译器允许?public bool Update(string category, string theater); public bool Update(string title, Actor a); public void Update(Actor b, Actor a, string title); public void Update(Actor a, Actor b);
public bool Update(string category, string theater);
public bool Update(string title, Actor a);
public void Update(Actor a, Actor b);
7、给定以下简单代码,展示了方法的重载、重写和直接继承,代码如下:class Vehicle { string name; public virtual void Fuel(string fuelType) {} public virtual bool Fuel(string fuelType, int amount) { return false; } } class Automobile : Vehicle { public virtual void Fuel(string fuelType, string timeFueled) {} public override bool Fuel(string fuelType, int amount) { return false; } } class Truck : Vehicle { public override void Fuel(string fuelType) {} } class SportsCar : Automobile { public override void Fuel(string fuelType) {} public override void Fuel(string fuelType, string timeFueled) {} } // 客户端代码: Truck t = new Truck(); SportsCar sc = new SportsCar(); 问这四个类分别能识别多少种不同的Fuel方法签名?
Vehicle类能识别2种 Automobile类能识别3种 Truck类能识别2种 SportsCar类能识别3种
8、哪些属于SRS类的字段可能适合声明为静态的?
对于学生类,代表学生总数的字段适合声明为静态,可表示大学中注册的学生总数;在SRS类中,用于组织对不同对象类型引用的集合对象字段适合声明为静态,如 、
scheduleOfClasses 、
faculty 、
studentBody ,可使这些主要对象集合在整个应用程序中全局可用。
courseCatalog
9、有人认为,C# 语言中声明和实现接口的能力消除了派生类从多个基类继承的需求。你同意还是不同意?为什么?你能想到与真正的多重继承相比,实现多个接口有哪些不足之处吗?
同意。C# 语言设计者因多重继承存在诸多复杂问题而未支持该特性,转而提供接口机制处理创建具有“多重特性”对象的需求。
一个类虽只能从一个直接基类派生,但可实现任意数量的接口,能在一定程度上替代多重继承。 实现多个接口的不足之处在于,接口中只有抽象方法声明,没有具体实现代码。 而多重继承中,派生类可直接继承多个基类的具体方法和字段实现。 若两个基类有相同签名但不同实现的方法: 多重继承能直接继承这些实现; 而接口无法提供具体实现,需在实现类中自行编写。
10、以下客户端代码场景都会导致编译错误,你能解释每种情况下为什么会这样吗?尽可能精确地说明原因,这些原因可能不像乍一看那么明显!假设Professor和StudentTeacher都是实现了ITeacher接口的类。场景1:Professor p; StudentTeacher s = new StudentTeacher(); ITeacher t; t = s; p = t; 场景2:Professor p = new Professor(); StudentTeacher s; ITeacher t = new StudentTeacher(); s = t; 场景3:Professor p = new Professor(); StudentTeacher s = new StudentTeacher(); ITeacher t; p = t;
## 场景1:
编译错误原因是 `t` 是 `ITeacher` 接口类型,`p` 是 `Professor` 类类型,虽然 `Professor` 实现了 `ITeacher` 接口,但不能直接将接口类型赋值给具体类类型,因为接口类型变量可能引用其他实现该接口的类的对象,存在类型不匹配问题。
## 场景2:
编译错误原因是 `t` 是 `ITeacher` 接口类型,`s` 是 `StudentTeacher` 类类型,不能直接将接口类型赋值给具体类类型,同样存在类型不匹配问题。
## 场景3:
编译错误原因是 `t` 未初始化,不能将未初始化的变量赋值给 `p`,同时即便 `t` 初始化了,也可能存在如场景1中类型不匹配的问题。
11、编写一个 C# 程序,以逆序打印出从 1 到 10 的整数。
以下是实现该功能的 C# 程序:
using System;
class Program
{
static void Main()
{
for (int i = 10; i >= 1; i--)
{
Console.WriteLine(i);
}
}
}
上述代码使用 循环从 10 递减到 1,并将每个整数打印输出。
for
12、使用自动实现属性重写“重写Equals方法”部分的代码。将测试代码改为使用对象初始化器语法来实例化Student对象。
以下是使用自动实现属性重写的代码,同时测试代码使用对象初始化器语法来实例化 对象:
Student
using System;
public class Student
{
// 自动实现属性
public string Id { get; set; }
// 重写Equals方法
public override bool Equals(object obj)
{
// 初始化标志
bool isEqual = false;
// 使用as运算符尝试将对象参数转换为Student对象。如果转换失败,该运算符返回null
Student s = obj as Student;
// 如果转换后的Student对象引用不为null,并且其Id属性值与当前Student对象相同,则将isEqual标志设置为true
if (s != null && s.Id == this.Id)
{
isEqual = true;
}
return isEqual;
}
}
public class Example
{
static void Main()
{
Professor p = new Professor();
// 使用对象初始化器语法实例化Student对象
Student s1 = new Student { Id = "123-45-6789" };
Student s2 = new Student { Id = "123-45-6789" };
Student s3 = new Student { Id = "987-65-4321" };
Console.WriteLine("Is s1 equal to s2? " + s1.Equals(s2));
Console.WriteLine("Is s1 equal to s3? " + s1.Equals(s3));
Console.WriteLine("Is s1 equal to p? " + s1.Equals(p));
}
}
public class Professor { }
13、编写一个简单的程序,创建一个泛型List集合,并用一系列随机字符串填充该集合。使用List类的一个方法(由你决定)对字符串进行字母排序。使用foreach循环遍历并输出排序后的名称。
以下是实现该功能的C#代码示例:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// 创建一个泛型List集合,用于存储字符串
List<string> stringList = new List<string>();
// 填充集合,这里添加一些示例字符串
stringList.Add("banana");
stringList.Add("apple");
stringList.Add("cherry");
stringList.Add("date");
// 使用Sort方法对字符串进行字母排序
stringList.Sort();
// 使用foreach循环遍历并输出排序后的名称
foreach (string str in stringList)
{
Console.WriteLine(str);
}
}
}
在上述代码中,首先创建了一个泛型 集合,然后向集合中添加了一些示例字符串。接着使用
List<string> 方法对集合中的字符串进行字母排序。最后,使用
Sort 循环遍历排序后的集合,并将每个字符串输出到控制台。
foreach
14、改进课程类的AddPrerequisite方法的逻辑,以确保课程不会意外地将自身指定为其先决条件。
在 方法中添加逻辑,检查要添加的先决条件课程是否为当前课程本身。若为本身,则不添加并可返回错误信息或抛出异常。示例代码如下:
AddPrerequisite
public class Course
{
private List<Course> prerequisites = new List<Course>();
public void AddPrerequisite(Course prerequisite)
{
if (prerequisite == this)
{
throw new ArgumentException("课程不能将自身指定为先决条件。");
}
prerequisites.Add(prerequisite);
}
}
15、改进教授类的AgreeToTeach方法的逻辑,使教授不会意外同意教授在同一日期/时间上课的两个不同课程小节。
为实现此需求,可在 类的
Professor 方法中添加逻辑,检查教授是否已有在相同日期和时间的课程小节安排。以下是示例代码:
AgreeToTeach
public class Professor {
private Collection<Section> sectionsTaught;
// 其他字段...
public bool AgreeToTeach(Section section) {
foreach (Section existingSection in sectionsTaught) {
if (existingSection.dayOfWeek == section.dayOfWeek && existingSection.timeOfDay == section.timeOfDay) {
return false; // 时间冲突,不能同意教授该小节
}
}
sectionsTaught.Add(section); // 时间不冲突,同意教授该小节
return true;
}
// 其他方法...
}
此代码中, 方法会遍历教授已教授的所有课程小节,检查是否有与新小节在同一天同一时间的课程。若有,返回
AgreeToTeach 表示不能同意;若没有,将新小节添加到已教授小节集合中并返回
false 。
true
16、高级练习:假设存在一个 ScheduleOfClasses 类,该类中有一个 SectionsOffered 字典用于存储课程章节信息,其键为课程相关标识,值为 Section 对象。该类的 Display 方法目前没有按课程名称的字母顺序列出课程章节;进行必要的更改以实现此功能。
可通过添加 方法将
GetSortedSections 字典中的内容转换为按字母顺序排序的
SectionsOffered 对象列表,然后在
Section 方法中使用该排序后的列表进行显示。示例代码如下:
Display
// Convert the contents of the SectionsOffered Dictionary
// into a List of Section objects that is sorted in
// alphabetical order
public List<Section> GetSortedSections() {
List<string> sortedKeys = new List<string>();
List<Section> sortedSections = new List<Section>();
// Load the sortedKeys List with the keys from the Dictionary
foreach ( KeyValuePair<string, Section> kv in SectionsOffered ) {
string key = kv.Key;
sortedKeys.Add(key);
}
// Sort the keys in the List alphabetically
sortedKeys.Sort();
// Load the value corresponding to the sorted keys into
// the sortedSections List
foreach( string key in sortedKeys ) {
Section s = SectionsOffered[key];
sortedSections.Add(s);
}
// Return the List containing the sorted Sections
return sortedSections;
}
在 方法中使用
Display 方法获取排序后的列表并进行显示。
GetSortedSections
17、高级练习:修改 SRS 应用程序,为用户提供设置其密码的功能。此过程将涉及以下步骤:向用户显示适当的错误消息;在主窗体上添加“设置密码”按钮;响应“设置密码”按钮的点击弹出一个对话框,要求用户输入旧密码和新密码(考虑创建一个“PasswordForm 类”的“克隆”);更改 Student.dat 文件的结构以适应存储学生的密码,这反过来将需要更改 Student 类的以下方法:ReadStudentData、WriteStudentData 和 Student 构造函数。
高级练习:修改 SRS 应用程序以支持密码设置
该高级练习要求修改 SRS 应用程序,以便用户能够设置密码。具体步骤如下:
向用户显示合适的错误消息。 在主窗体中添加“设置密码”按钮。 点击“设置密码”按钮时弹出对话框,让用户输入旧密码和新密码。可以考虑创建 类的“克隆”。 更改
PasswordForm 文件结构,以存储学生密码。同时需要修改
Student.dat 类的以下部分:
Student
– 方法
ReadStudentData
– 方法
WriteStudentData
– 构造函数
Student
18、访问微软 .NET 框架主页 http://msdn.microsoft.com/en-us/library/w0x726c2.aspx,了解 .NET 框架提供的库和功能,并说明这些库和功能对 C# 开发有什么作用。
访问指定网页,了解 .NET 框架 提供的库和功能。C# 可以利用这些库和功能进行开发,例如使用框架提供的类库实现特定的功能,提高开发效率和代码质量。