15个基本的c#面试问题 *
最好的c#开发人员和工程师可以回答的全部基本问题. 在我们社区的推动下,我们鼓励专家提交问题并提供反馈.
现在就聘请一名顶级c#开发人员面试问题
下面这个短程序的输出是什么? 解释你的答案.
class Program {
静态字符串位置;
静态DateTime时间;
静态void Main() {
Console.WriteLine(location == null ? "位置为空": location);
Console.WriteLine(time == null ? time is null:时间.ToString());
}
}
输出将是:
位置为空
1/1/0001 12:00:00 AM
尽管这两个变量都未初始化, String
引用类型是and吗 DateTime
is a value type. 作为值类型,初始化的 DateTime
变量被设置为默认值午夜1/1/1(是的,那是a年.D.), not null
.
当然,有很多方法可以做到这一点,但最直接的两种方法是:
TotalAllEvenNumbers(int[] intArray) {
return intArray.Where(i => i % 2 == 0).Sum(i => (long)i);
}
or:
TotalAllEvenNumbers(int[] intArray) {
return (from i in intArray where i % 2 == 0 select (long)i).Sum();
}
以下是在答案中寻找的关键内容:
- 候选人是否充分利用了c#语言结构,使单行解决方案成为可能(i.e., 而不是使用包含循环的冗长解决方案, 条件语句, 和蓄电池)?
- 候选人是否考虑过溢出的可能性. 例如,这样的实现
return intArray.Where(i => i % 2 == 0).Sum()
(不管函数的返回类型是什么)可能是一个“显而易见的”单行解决方案, 但是这里溢出的概率很高. 而上述答案中使用的方法是转换为long
并不能排除这种可能性, 这使得发生溢出异常的可能性极小. Note that, 如果候选人询问数组的预期大小及其成员的大小, 他或她显然在考虑这个溢出问题, 这是我们想要确定的.
的比较 time
and null
in the if
下面的陈述是否有效? Why or why not?
静态DateTime时间;
/* ... */
If (time == null)
{
/*做某事*/
}
有人可能会想,既然a DateTime
变量永远不能为空(它会自动初始化为1月1日), 0001), 编译器会报错 DateTime
变量与 null
. However, 由于类型强制, 编译器允许这样做, 这可能会导致假头和拔毛虫.
具体来说, ==
操作符将其操作数强制转换为不同的允许类型,以便在两边获得共同的类型, 然后它可以比较哪个. 这就是为什么像这样的东西会给你期望的结果(而不是失败或异常行为,因为操作数是不同的类型):
double x = 5.0;
int y = 5;
Console.WriteLine(x == y); // outputs true
然而,这有时会导致意想不到的行为,就像比较 DateTime
variable and null
. 在这种情况下,两者 DateTime
变量和 null
Literal可以强制转换为 Nullable
. 因此,比较这两个值是合法的,即使结果会 always be false.
给定一个实例 circle
属于下列类别:
公共密封类Circle {
专用双半径;
public double Calculate(Func op) {
返回op(半径);
}
}
写代码计算圆的周长,无需修改 Circle
class itself.
首选的答案是:
circle.Calculate(r => 2 * Math.PI * r);
因为我们无法进入 private radius
对象的字段, 我们告诉物体自己计算周长, 通过内联传递计算函数.
许多c#程序员回避(或不理解)函数值形参. 虽然在这种情况下,这个例子有点做作, 目的是看申请人是否理解如何制定一个电话到 Calculate
哪个匹配方法的定义.
Alternatively, 一个有效(虽然不太优雅)的解决方案是从对象中检索半径值本身,然后用结果执行计算:
半径=圆.Calculate(r => r);
var圆周= 2 *数学.PI * radius;
两种方法都可以. 我们在这里主要看的是应聘者是否熟悉, 并且知道如何调用, the Calculate
method.
下面程序的输出是什么? 解释你的答案.
class Program {
私有静态字符串结果;
静态void Main() {
SaySomething();
Console.WriteLine(结果);
}
static async Task SaySomething() {
await Task.Delay(5);
result = "Hello world .!";
返回“东西”;
}
}
同样,如果我们替换 await Task.Delay(5);
with Thread.Sleep(5)
? Why or why not?
问题第一部分的答案(1).e.,代码的版本 await Task.Delay(5);
)是程序将只输出一个空行(not “Hello world!”). 这是因为 result
何时仍未初始化 Console.WriteLine
is called.
大多数面向过程和面向对象的程序员都希望函数从头到尾执行, or to a return
语句,然后返回调用函数. 这与c#不同 async
functions. 它们只执行到第一次 await
语句,然后返回给调用者. 调用的函数 await
(in this case Task.Delay
)是异步执行的,并且 await
语句没有发出执行信号,直到 Task.Delay
完成(5毫秒). 但是,在此时间内,控制权已经返回给调用方,调用方执行 Console.WriteLine
语句在尚未初始化的字符串上执行.
Calling await Task.Delay(5)
让当前线程继续它正在做的事情, 如果完成了(等待完成), 将其返回到线程池. 这是async/await机制的主要好处. 它允许CLR在线程池中使用更少的线程来服务更多的请求.
异步编程已经变得越来越普遍, 随着对许多活动执行网络服务请求或数据库请求的设备的流行. c#有一些优秀的编程结构,极大地简化了异步方法的编程任务, 意识到这一点的程序员会写出更好的程序.
关于问题的第二部分,如果 await Task.Delay(5);
取而代之的是 Thread.Sleep(5)
,程序将输出 Hello world!
. An async
method without at least one await
statement in it operates just like a synchronous method; that is, 它将从头到尾执行, 或者直到它遇到 return
statement. Calling Thread.Sleep()
阻塞当前正在运行的线程,所以 Thread.Sleep(5)
的执行时间增加了5毫秒 SaySomething()
method.
下面程序的输出是什么? 解释你的答案.
委托无效打印机();
Main()
{
List printers = new List();
int i=0;
for(; i < 10; i++)
{
printers.添加委托{控制台.WriteLine(i); });
}
Foreach(打印机中的var printer)
{
printer();
}
}
这个程序将输出10这个数字10次.
原因如下:委托被添加到for循环中,并且“引用”(或者“指针”可能是更好的选择)到 i
是存储的,而不是值本身. 因此,在我们退出循环之后,变量 i
已设置为10,因此在调用每个委托时,传递给所有委托的值都是10.
Yes! 这样做是可能的,因为数组可以是类型 object
它不仅可以存储任何数据类型,还可以存储类的对象,如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
名称空间ConsoleApplication8
{
class Program
{
class Customer
{
public int ID { get; set; }
public string Name { get; set; }
公共覆盖字符串ToString()
{
return this.Name;
}
}
静态void Main(string[] args)
{
对象[]数组=新对象[3];
数组[0]= 101;
数组[1]= " c# ";
Customer c = new Customer();
c.ID = 55;
c.Name = "Manish";
array[2] = c;
Foreach(对象对象)
{
Console.WriteLine (obj);
}
Console.ReadLine();
}
}
}
c#中的类和结构确实有一些共同之处,即:
- 是复合数据类型
- 可以包含方法和事件吗
- 可支持接口
但也有一些不同之处. 这里有一个比较:
Classes:
- 支持继承
- 是引用(指针)类型吗
- 引用可以为空
- 每个新实例都有内存开销
Structs:
- 不支持继承
- 是值类型
- 按值传递(如整数)
- 不能有空引用(除非使用Nullable)
- 每个新实例没有内存开销(除非“盒装”)
下面程序的输出是什么?
公共类TestStatic
{
public static int TestValue;
公共TestStatic ()
{
if (TestValue == 0)
{
TestValue = 5;
}
}
静态TestStatic ()
{
if (TestValue == 0)
{
TestValue = 10;
}
}
Print()
{
if (TestValue == 5)
{
TestValue = 6;
}
Console.WriteLine("TestValue: " + TestValue);
}
}
public void Main(string[] args)
{
TestStatic = new TestStatic();
t.Print();
}
TestValue : 10
在创建类的任何实例之前调用类的静态构造函数. 的静态构造函数初始化 TestValue
variable first.
class ClassA
{
public ClassA() {}
public ClassA(int pValue) {}
}
在客户端:
class Program
{
静态void Main(string[] args)
{
ClassA refA = new ClassA();
}
}
Question:
有办法修改吗 ClassA
这样你就可以调用带参数的构造函数, 当Main方法被调用时, 类的任何其他新实例 ClassA
?
The this
关键字用于调用其他构造函数,以初始化类对象. 实现如下:
class ClassA
{
public ClassA(): this(10)
{ }
public ClassA(int pValue)
{ }
}
下面的代码输出什么?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
小说名称空间
{
class Program
{
静态void Main(string[] args)
{
try
{
Console.WriteLine(“Hello”);
}
抓住(ArgumentNullException)
{
Console.WriteLine(“A”);
}
抓住(异常)
{
Console.WriteLine("B");
}
finally
{
Console.WriteLine("C");
}
Console.ReadKey();
}
}
}
Hello
C
using system;
class abc
{
public static Void Main()
{
Int ndistance, nresult;
Console.WriteLine("以公里为单位输入距离");
Ndistance = convert.ToInt32(Console.ReadLine());
Nresult = ndistance * 1000;
Console.WriteLine("距离以米为单位:" + nresult);
Console.ReadLine();
}
}
装箱是值类型到类型的隐式转换 object
或由值类型实现的任何接口类型. 装箱一个值类型会创建一个包含该值的对象实例,并将其存储在堆上.
Example:
int x = 101;
object o = x; // boxing value of x into object o
o = 999;
x = (int)o; // unboxing value of o into integer x
给定一个至少包含一个的字串 $
symbol, e.g.:
“foo bar foo $ bar $ foo bar $”
问:如何除去除第一次出现外的所有 $
从一个给定的字符串?
这个问题有两个部分:保留第一个出现的元素,替换所有其他的元素.
我们可以用正则表达式求解 String.Replace()
:
using System;
using System.Text.RegularExpressions;
类MainClass {
Main (string[] args) {
字符串s = "例如$你没有$网络$访问权限";
Console.WriteLine("before: {0}", s);
GroupCollection semiconductors = Regex.匹配的 , @"([^$]*\$)(.*)").Groups;
字符串答案=一半[1].Value + / 2 [2].Value.取代 ("$", "");
Console.WriteLine("after: {0}", answer);
//例如$你没有网络访问权限
}
}
Explanation:
-
([^$]*\$)
-组1捕获任意数量的非-$
字符,加上一个$
字符(用。转义\
) -
(.*)
-第二组(贪婪地)捕获其他一切
的第一次出现 $
preserved in halves[1].Value
,我们可以简单地使用 String.Replace()
on halves[2].Value
消除所有 $
在字符串的其余部分中找到的字符,不需要第二个正则表达式.
面试不仅仅是棘手的技术问题, 所以这些只是作为一个指南. 并不是每一个值得雇佣的“A”候选人都能回答所有的问题, 回答所有问题也不能保证成为A级考生. 一天结束的时候, 招聘仍然是一门艺术,一门科学,需要大量的工作.
Why Toptal
提出面试问题
提交的问题和答案将被审查和编辑, 并可能会或可能不会选择张贴, 由Toptal全权决定, LLC.
寻找c#开发人员?
Looking for C# Developers? 查看Toptal的c#开发人员.
Rory Woods
自由c#开发人员
Rory是一名软件顾问,提供满足企业需求的解决方案. 他带来了技术技能和经验,不仅指导团队如何构建,还指导团队构建什么. 他在微软web堆栈方面拥有丰富的经验,包括ASP.NET MVC、Web API、SQL Server和Azure.
Show MoreRizwan Rizvi
自由c#开发人员
里兹万以通过清晰的思维克服复杂的挑战而闻名, 创新的方法, 加强组织不同部门之间的沟通. 在他的职业生涯中, 他优化了多样化和分散的IT专业人员团队的工作,并在具有挑战性的环境中始终如一地交付了有利可图的项目.
Show MoreDan Napierski
自由c#开发人员
Dan是一名专注于区块链技术应用的软件架构师和技术专家. 他拥有多年的专业咨询服务经验,为从初创公司到跨国公司的客户提供服务. 他擅长将严格的测试和防弹代码引入棘手的工程挑战. 他在人工智能的许多方面都有深厚的专业知识, blockchain, 机器学习, and automation.
Show MoreToptal连接 Top 3% 世界各地的自由职业人才.
加入Toptal社区.