提交 15539b61 编写于 作者: 幻灰龙's avatar 幻灰龙

Merge branch 'master' into 'master'

添加 2..NET中阶\1.ASP.NET Core应用\4.Web API应用

See merge request !2
{
"type": "code_options",
"author": "Gao996",
"source": "AnonymousType.md",
"exercise_id": "47413f9f257545289bc30c177ce14d37",
"notebook_enable": false
}
\ No newline at end of file
# C# 3.0 特性 匿名类型
匿名类型提供了一种方便的方法,可以将一组只读属性封装到单个对象中,而无需先显式定义类型。类型名称由编译器生成,在源代码级别不可用。每个属性的类型由编译器推断。
您可以通过将new运算符与对象初始值设定项一起使用来创建匿名类型。
```csharp
var user = new { name = "Gao", id = 996, height = 172.5 }; // 此时编译器会提示匿名类型, 是 new {string name, int id, double height}
Console.WriteLine(string.Format("name {0}, id {1}, height {2}", user.name, user.id, user.height));
```
如果一个类里面的属性和字段太多,想要用LINQ语句查找,可以试试匿名类型。以下代码举个例子,假如有一个examples是example类的集合,然后输出所有的Name,如果直接查询会把example类的所有属性和字段带过来,使用匿名类型会导致查询中返回的数据量较少。
```csharp
var result = from example in examples select new { example.Name };
foreach (var item in result)
{
Console.WriteLine(item.Name);
}
```
在下列选项中,可以设置一个name是“csdn”的匿名类型的是:
## 答案
```csharp
var csdn = new { name = "csdn" };
```
## 选项
### A
```csharp
var csdn = { name = "csdn" };
```
### B
```csharp
var csdn = new CSDN(){ name = "csdn" };
```
### C
```csharp
var csdn = new() { name = "csdn" };
```
\ No newline at end of file
{
"type": "code_options",
"author": "Gao996",
"source": "AutoImplementedProperties.md",
"exercise_id": "ce894b0d3ce14592a0af56e06a32854d",
"notebook_enable": false
}
\ No newline at end of file
# C# 3.0 特性 自动实现属性
在 C# 3.0 及更高版本,当属性访问器中不需要任何其他逻辑时,自动实现的属性会使属性声明更加简洁。
对于字段可以用属性来封装,上面代码的name就是用Name封装,并且使用时使用Name。C# 3.0特性支持了自动实现属性的访问器,这样就可以写成Id这样,也能实现一样的功能。这里的属性将set访问器声明为私有,那就是私有的访问级别,如果访问器只声明get访问器时,除了能在构造函数中可变,在其他任何位置都不可变。
```csharp
public class Example
{
private string name;
public string Name { get => name; set => name = value; }
public string Id { get; set; }
public int Count { get; private set; }
public string UserId { get;}
public Example(string userId)
{
this.UserId = userId;
}
}
```
如上代码,在下列选项中,不可以设置属性值的是:
## 答案
```csharp
Example example = new Example(){UserId = Guid.NewGuid().ToString()};
```
## 选项
### A
```csharp
Example example = new Example(Guid.NewGuid().ToString());
```
### B
```csharp
Example example = new Example();
example.Id = Guid.NewGuid().ToString();
```
### C
```csharp
Example example = new Example();
example.Name = Guid.NewGuid().ToString();
```
\ No newline at end of file
{
"type": "code_options",
"author": "Gao996",
"source": "ExpressionTree.md",
"exercise_id": "ea23a2f4010a4dd398b477d4990547a7",
"notebook_enable": false
}
\ No newline at end of file
# C# 3.0 特性 表达式树
表达式树是定义代码的数据结构。 它们基于编译器用于分析代码和生成已编译输出的相同结构。
以下代码创建了一个表达式并且执行了,Compile方法可以编译表达式树由描述为可执行代码的 lambda 表达式,并生成一个委托,表示 lambda 表达式。
注意这里不能使用var来声明此表达式树,因为此操作无法执行,这是由于赋值右侧是隐式类型而导致的。
```csharp
Expression<Func<int>> add = () => 1 + 2;
var func = add.Compile(); // 创建一个 delegate
var answer = func(); // 调用 delegate, 得到值3
Console.WriteLine(answer);
```
根据上面例子,下列选项中,可以生成一个1+2的表达式的是:
## 答案
```csharp
var one = Expression.Constant(1, typeof(int));
var two = Expression.Constant(2, typeof(int));
var addition = Expression.Add(one, two);
```
## 选项
### A
```csharp
var one = Expression.Constant(1);
var two = Expression.Constant(2);
var addition = Expression.Add(one, two);
```
### B
```csharp
var one = (Expression)1;
var two = (Expression)2;
var addition = Expression.Add(one, two);
```
### C
```csharp
var one = Expression.Constant(1, typeof(int));
var two = Expression.Constant(2, typeof(int));
var addition = one + two;
```
\ No newline at end of file
{
"type": "code_options",
"author": "Gao996",
"source": "ExtensionMethod.md",
"exercise_id": "2b4114f71e59455099471a65d2b0885f",
"notebook_enable": false
}
\ No newline at end of file
# C# 3.0 特性 扩展方法
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。
扩展方法是一种静态方法,但可以像扩展类型上的实例方法一样进行调用。调用扩展方法与调用在类型中定义的方法没有明显区别。
在下列选项中,是扩展方法并实现了判断字符串中是否包含Q或q的代码的是:
## 答案
```csharp
public static class Extensions
{
public static bool IsContainQ(this String str)
{
foreach (var item in str)
{
if (item.Equals('Q') || item.Equals('q'))
{
return true;
}
}
return false;
}
}
```
## 选项
### A
```csharp
public class Extensions
{
public bool IsContainQ(this String str)
{
foreach (var item in str)
{
if (item.Equals('Q') || item.Equals('q'))
{
return true;
}
}
return false;
}
}
```
### B
```csharp
public static class Extensions
{
public static bool IsContainQ(this)
{
foreach (var item in str)
{
if (item.Equals('Q') || item.Equals('q'))
{
return true;
}
}
return false;
}
}
```
### C
```csharp
public static class Extensions
{
public static bool IsContainQ(String str)
{
foreach (var item in str)
{
if (item.Equals('Q') || item.Equals('q'))
{
return true;
}
}
return false;
}
}
```
\ No newline at end of file
{
"type": "code_options",
"author": "Gao996",
"source": "LambdaExpression.md",
"exercise_id": "99b3ef51bbb74e46b987729b18c9e311",
"notebook_enable": false
}
\ No newline at end of file
# C# 3.0 特性 Lambda 表达式
Lambda表达式可采用表达式为其主体,也可以采用语句块作为其主体:
```csharp
(input-parameters) => expression
(input-parameters) => { <sequence-of-statements> }
```
Lambda表达式可以没有参数,如果有参数需要在左侧添加,任何 Lambda 表达式都可以转换为委托类型。
在下列选项中,没有编译错误并且可以输出5的平方的是:
## 答案
```csharp
Func<int, int> square = x => x * x;
Console.WriteLine(square(5));
```
## 选项
### A
```csharp
Func<int, int> square = () => x * x;
Console.WriteLine(square(5));
```
### B
```csharp
Func<int, int> square = x * x;
Console.WriteLine(square(5));
```
### C
```csharp
Func<int, int> square => x * x;
Console.WriteLine(square(5));
```
\ No newline at end of file
{
"type": "code_options",
"author": "Gao996",
"source": "QueryExpression.md",
"exercise_id": "20602ef8b2bf49cab1a5f3ff66523b10",
"notebook_enable": false
}
\ No newline at end of file
# C# 3.0 特性 查询表达式
查询表达式必须以from子句开头。 它指定数据源以及范围变量。查询表达式以select或group结尾。
* 使用 where 子句可基于一个或多个谓词表达式,从源数据中筛选出元素。
* 使用 select 子句可生成所有其他类型的序列。
* 使用 group 子句可生成按指定键组织的组的序列。
* 使用 into 关键字可以在 select 或 group 子句中创建存储查询的临时标识符。
* 使用 orderby 子句可按升序或降序对结果进行排序。
* 使用 join 子句可基于每个元素中指定的键之间的相等比较,将一个数据源中的元素与另一个数据源中的元素进行关联和/或合并。
* 使用 let 子句可将表达式(如方法调用)的结果存储在新范围变量中。
在下列选项中,可以将examples集合中所有Count大于10的子项目按照Count从大到小的顺序格式化显示的是:
## 答案
```csharp
from example in examples
where example.Count > 10
orderby example.Count descending
select $"{example.Name}\t{example.Count}";
```
## 选项
### A
```csharp
from example in examples
where example.Count > 10
orderby example.Count ascending
select $"{example.Name}\t{example.Count}";
```
### B
```csharp
from example in examples
where example.Count > 10
orderby example.Count
select $"{example.Name}\t{example.Count}";
```
### C
```csharp
from example in examples
where example.Count > 10
orderby example.Name ascending
select $"{example.Name}\t{example.Count}";
```
\ No newline at end of file
// 自动实现的属性
public class Example
{
private string name;
public string Name { get => name; set => name = value; }
public string Id { get; set; }
public int Count { get; private set; }
public string UserId { get;}
public Example(string userId)
{
this.UserId = userId;
}
}
// 匿名类型
var user = new { name = "Gao", id = 996, height = 172.5 }; // 此时编译器会提示匿名类型, 是 new {string name, int id, double height}
Console.WriteLine(string.Format("name {0}, id {1}, height {2}", user.name, user.id, user.height));
var result = from example in examples select new { example.Name };
foreach (var item in result)
{
Console.WriteLine(item.Name);
}
// 查询表达式
from example in examples
where example.Count > 10
orderby example.Count descending
select $"{example.Name}\t{example.Count}";
// Lambda 表达式
Func<int, int> square = x => x * x;
Console.WriteLine(square(5));
// 表达式树
Expression<Func<int>> add = () => 1 + 2;
var func = add.Compile(); // 创建一个 delegate
var answer = func(); // 调用 delegate, 得到值3
Console.WriteLine(answer);
// 扩展方法
public static class Extensions
{
public static bool IsContainQ(this String str)
{
foreach (var item in str)
{
if (item.Equals('Q') || item.Equals('q'))
{
return true;
}
}
return false;
}
}
// 隐式类型本地变量
// 分部方法
// 对象和集合初始值设定项
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
{
"type": "code_options",
"author": "Gao996",
"source": "WebAPI.md",
"exercise_id": "7387559d89a94c03a5dc8a963b0327a0",
"notebook_enable": false
}
\ No newline at end of file
# Web API应用
应用程序接口(API,Application Programming Interface)是基于编程语言构建的结构,使开发人员更容易地创建复杂的功能。它们抽象了复杂的代码,并提供一些简单的接口规则直接使用。
当我们创建一个.net Core的Web API时,可以选择带有模板的,这样就自动生成了一个简单的API,而且调试的时候也会自动生成[swagger](https://swagger.io/ "swagger")打开网页可查看接口详细信息和测试。如下是ValueController的代码。
```csharp
[Route("api/[controller]")] // 自定义特性,调用接口时可以"https://localhost/api/Values"(这里[controller]是继承ControllerBase的类名,也可以拼接很多,比如加[action]是方法名)
[ApiController]
public class ValuesController : ControllerBase
{
// GET: api/<ValuesController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
```
此时用GET调用接口会返回
```json
[
"value1",
"value2"
]
```
Web API还允许在方法中使用特性来切换请求方式和参数方式:
```csharp
// GET api/<ValuesController>/5
[HttpGet("{id}")] // 这里的{id}就是参数id
public string Get(int id)
{
return (id * 2).ToString();
}
// POST api/<ValuesController>
[HttpPost] // 这里用了POST方法
public void Post([FromBody] string value) //FromBody特性,curl -X POST "https://localhost/api/Values" -H "accept: */*" -H "Content-Type: application/json" -d "\"string\""
{
}
// PUT api/<ValuesController>/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/<ValuesController>/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
```
```csharp
[Route("api/[controller]/[action]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet]
public string Sum(string num1, string num2)
{
int num1Length = num1.Length;
int num2Length = num2.Length;
int maxLength = Math.Max(num1Length, num2Length);
num1 = num1.PadLeft(maxLength, '0');
num2 = num2.PadLeft(maxLength, '0');
int sum = 0, ans = 0;
string result = string.Empty;
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= maxLength; i++)
{
sum = num1[maxLength - i] - '0' + num2[maxLength - i] - '0' + ans;
if (sum >= 10)
{
sum = sum % 10;
ans = 1;
}
else
{
ans = 0;
}
sb.Append(sum);
}
if (ans == 1)
{
sb.Append(1);
}
result = string.Join("", sb.ToString().Reverse());
return result;
}
[HttpGet("{str}")]
public string Copy(string str)
{
return str;
}
}
```
如上代码,在下列选项中,可以正确获取Test接口的是:
## 答案
```
curl -X GET "https://localhost:44326/api/Test/Sum?num1=6&num2=6" -H "accept: text/plain"
curl -X GET "https://localhost:44326/api/Test/Copy/str" -H "accept: text/plain"
```
## 选项
### A
```
curl -X GET "https://localhost:44326/api/Test/Sum/6&6" -H "accept: text/plain"
curl -X GET "https://localhost:44326/api/Test/Copy/str" -H "accept: text/plain"
```
### B
```
curl -X GET "https://localhost:44326/api/Test/Sum?num1=6&num2=6" -H "accept: text/plain"
curl -X GET "https://localhost:44326/api/Test/Copy?str=str" -H "accept: text/plain"
```
### C
```
curl -X GET "https://localhost:44326/api/Test/Sum/6&6" -H "accept: text/plain"
curl -X GET "https://localhost:44326/api/Test/Copy?str=str" -H "accept: text/plain"
```
\ No newline at end of file
// Test API
[Route("api/[controller]/[action]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet]
public string Sum(string num1, string num2)
{
int num1Length = num1.Length;
int num2Length = num2.Length;
int maxLength = Math.Max(num1Length, num2Length);
num1 = num1.PadLeft(maxLength, '0');
num2 = num2.PadLeft(maxLength, '0');
int sum = 0, ans = 0;
string result = string.Empty;
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= maxLength; i++)
{
sum = num1[maxLength - i] - '0' + num2[maxLength - i] - '0' + ans;
if (sum >= 10)
{
sum = sum % 10;
ans = 1;
}
else
{
ans = 0;
}
sb.Append(sum);
}
if (ans == 1)
{
sb.Append(1);
}
result = string.Join("", sb.ToString().Reverse());
return result;
}
[HttpGet("{str}")]
public string Copy(string str)
{
return str;
}
}
// Value API
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET: api/<ValuesController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<ValuesController>/5
[HttpGet("{id}")]
public string Get(int id)
{
return (id * 2).ToString();
}
// POST api/<ValuesController>
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/<ValuesController>/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/<ValuesController>/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册