据我所知,yield
关键字,如果从迭代器块内部使用,它会将控制流返回给调用代码,当再次调用迭代器时,它会从中断处继续.
此外,await
不仅等待被调用者,而且还将控制权返回给调用者,仅在调用者调用awaits
方法时从中断处获取.
换句话说 - 没有线程,async和await的"并发"是一种由巧妙的控制流引起的错觉,其细节被语法隐藏.
现在,我是一名前汇编程序员,我对指令指针,堆栈等非常熟悉,并且我得到了正常的控制流(子程序,递归,循环,分支)的工作方式.但是这些新的结构 - 我没有得到它们.
当await
到达,如何运行时知道什么是一段代码接下来应该执行?它是如何知道什么时候可以从它停止的地方恢复的,它如何记住在哪里?当前的调用堆栈会发生什么,它会以某种方式保存吗?如果调用方法在其之前进行其他方法调用,那么该await
怎么办?为什么堆栈不会被覆盖呢?在异常和堆栈展开的情况下,运行时如何在所有这些中运行?
何时yield
到达,运行时如何跟踪应该拾取事物的点?迭代器状态如何保存?
我刚开始使用 .net core,发现Action<T>
到处都在使用。我从下面的 Swagger 代码块中提供了示例代码。我的问题是使用Action<T>
这里有什么用?我需要传递配置数据。Swagger 如何提取配置数据?
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info
{
Version = "v1",
Title = "My API",
Description = "My First ASP.NET Core Web API",
TermsOfService = "None",
Contact = new Contact() { Name = "Talking Dotnet", Email = "x@x.com", Url = "www.x.com" }
});
});5
Run Code Online (Sandbox Code Playgroud) 我有一个便利类,它本质上是一个字典,它包含一个标记/值对列表,用于提交给API.
在最基本的层面上,我所做的就是:
enum Tag
{
Name, Date, //There are many more
}
class RequestDictionary : Dictionary<Tag, string>
{
}
Run Code Online (Sandbox Code Playgroud)
这很好地映射了API的需求,因为整个事件被发送并解析为字符串.然而,对于来电者来说并不是那么好; 例如,调用者必须知道如何Date
正确格式化.
为了解决这个问题,我开始添加类型安全的特定于标签的属性.我将它们隔离在单独的界面中,这样它们就不会与普通的Dictionary属性混淆.
enum Tag
{
Name, Date
}
interface ITags
{
string Name { get; set; }
DateTime Date { get; set; }
}
class RequestDictionary : Dictionary<Tag, string>, ITags
{
public ITags Tags { get { return this; } }
string ITags.Name
{
get { return this[Tag.Name]; }
set { this[Tag.Name] = value; }
}
DateTime …
Run Code Online (Sandbox Code Playgroud) 我想知道当需要来自多个记录的单个值时,是否有一些聪明的方法可以使用LINQ从可枚举中检索数据.
例如,假设您有一个拥有三个不同电话字段的人:
public class Person
{
public Phone HomePhone { get; set; }
public Phone WorkPhone { get; set; }
public Phone CellPhone { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
...但电话列表以标准化格式存储:
public enum PhoneType
{
Home, Work, Cell
}
public class Phone
{
public PhoneType Type { get; set; }
public string Number { get; set; }
}
static public IEnumerable<Phone> GetPhoneList()
{
yield return new Phone { Type = PhoneType.Home, Number = "8005551212" };
yield return new Phone { Type = …
Run Code Online (Sandbox Code Playgroud) 我的站点调用一个服务(让我们称之为FooService),它需要一组非常复杂的身份验证协议.这些协议都包含在自定义的ClientCredentials行为中,该行为在代码中声明如下:
class FooServiceCredentialsBehavior : ClientCredentials
{
public FooServiceCredentialsBehavior()
{
//Set up service certificate
var cert = CertStore.FindBySerialNumber(certSerialNumber);
base.ServiceCertificate.DefaultCertificate = cert;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们注册行为扩展:
<behaviorExtensions>
<add name="FooServiceCredentials" type="MyProject.Namespace.FooService, MyProject" />
</behaviorExtensions>
Run Code Online (Sandbox Code Playgroud)
配置endpointBehavior以使用它:
<endpointBehaviors>
<behavior name="FooServiceCredentialsBehavior">
<FooServiceCredentials />
</behavior>
Run Code Online (Sandbox Code Playgroud)
并设置端点以使用它:
<endpoint address="https://fooservice.com/bar"
behaviorConfiguration="FooServiceCredentialsBehavior"
contract="FooService_PortType" />
Run Code Online (Sandbox Code Playgroud)
以上所有工作都很完美,并且已经为许多客户服务多年.
我现在正在将这些内容部署到无法访问CRL服务器的系统,并且自定义行为包括已启用验证的服务证书.所以我需要关闭验证.但是我无法修改FooServiceCredentials类.如果可以,我会这样做:
base.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
Run Code Online (Sandbox Code Playgroud)
但我不能.
我想知道是否可以添加应用于将执行相同操作的自定义凭据行为的WCF配置.像这样的东西:
<endpointBehaviors>
<behavior name="FooServiceCredentialsBehavior">
<FooService>
<ServiceCertificate>
<authentication certificateValidationMode="None"/>
</ServiceCertificate>
</FooService>
</behavior>
Run Code Online (Sandbox Code Playgroud)
这个确切的XML不起作用(该服务甚至不会启动)但我希望有一些神奇的方法可以安排这些标签来禁用仅来自配置的服务证书验证.
可能吗?怎么样?
我正在开发一个有一些有趣的Javascript的网站,我担心它可能会导致速度较慢的机器出现性能问题.
该脚本使用setInterval来运行处理程序EVERY SECOND.处理程序执行以下操作:
cookie有一个到期日期,所以理论上它应该每次写入磁盘,而不是保存在内存中.
到目前为止它在我的电脑上工作得很好,但我有一台带有固态硬盘的快速机器.你认为这种设计会在较慢的盒子或繁忙的硬盘上引起问题吗?可能导致每1秒发生一次轻微的口吃效果?只是寻找一些保证,这种设计并非绝对疯狂.谢谢.
我有一个程序,必须处理多个对象并进行分析。每个分析都会产生一个字符串,并将这些字符串连接起来以创建一个报告。报告需要按一定顺序排列结果,但我想异步分析每个项目,因此我将所有内容放入字典中进行管理,然后可以在准备最终输出之前对其进行排序。
注意:在本例中,我将假装我们正在分析当前程序集中的类型,尽管在我看来,它比这要复杂得多。
(我认为)执行此操作的基本模式如下:
var types = myAssembly.GetTypes();
var tasks = types.ToDictionary( key => key, value => AnalyzeType(value) );
//AnalyzeType() is an async method that returns Task<string>.
Run Code Online (Sandbox Code Playgroud)
现在我们有了一个热门任务字典,由于我什么都没等,所以在创建字典时可能会完成也可能不会完成。
现在获取结果。我该怎么做?
等待
从理论上讲,我要做的就是等待每个任务。等待操作的结果是值本身。但这并不能转换任何东西。
var results = tasks.ToDictionary( k => k.key, async v => await v.Value );
Console.WriteLine(results.GetType().FullName);
Run Code Online (Sandbox Code Playgroud)
输出:
System.Collections.Generic.Dictionary'2[[System.Type, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Threading.Tasks.Task'1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
我感到困惑……我想通过将await
Task 放在前面,C#会将其转换为结果。但是我还有任务字典。
GetResult()
另一种方法是使用此方法:
var results = tasks.ToDictionary( key => key, value => value.GetAwaiter().GetResult() );
Console.WriteLine(results.GetType().FullName);
Run Code Online (Sandbox Code Playgroud)
输出:
System.Collections.Generic.Dictionary'2[[System.Type, mscorlib, Version=4.0.0.0, …
我很清楚如何自己设置它,但我担心在两个不同的地方配置它。要获得赏金,请告诉我应该在哪里寻找现有设置。
我们已经寻找现有设置的地方,但没有成功:
<StaticContent>
部分SetMaxAge
)我们最近注意到我们的 CSS 和 JS 文件没有得到刷新。当我检查网络流量时,它们从服务器返回,并带有一个标头 ( Cache-Control: max-age=604800
),该标头为它们提供了 7 天的生命周期。
我们需要减少缓存寿命。但对于我的生活,我找不到它的位置。
它没有在 web.config<StaticContent>
部分中设置。
它没有在 IIS 输出缓存部分设置(我查看了机器、站点和应用程序——它们都是空白的)。
它没有在代码中设置——我进行了全局代码搜索SetMaxAge
并得到了 nuthin'。我还能在哪里看?
它可能是由我们数据中心的网关或负载均衡器设置的吗?
可插拔框架
想象一个简单的可插拔系统,使用继承多态非常简单:
IRenderer
,因此它们都可以存储在一个IRenderer[]
.IRenderer[]
会填充一系列特定的渲染器Render
方法调用插件,将形状作为其基本类型传递.Render
在每个后代类中重写该方法; 它将Shape转换回其后代类型,然后呈现它.希望以上是清楚的 - 我认为这是一种非常常见的设置.使用继承多态和运行时强制转换非常容易.
没有铸造它
现在是棘手的部分.在回答这个问题时,我想想办法在没有任何铸造的情况下完成这一切.这是因为IRenderer[]
该数组很棘手 - 要从数组中获取插件,通常需要将其转换为特定类型才能使用其特定于类型的方法,我们不能这样做.现在,我们可以通过仅与其基类成员交互插件来解决这个问题,但部分要求是渲染器必须运行特定于类型的方法,该方法具有特定于类型的数据包作为参数,并且基础class无法做到这一点,因为没有办法将它传递给特定类型的数据包而不将其转移到基础然后再回到祖先.棘手.
起初我认为这是不可能的,但经过几次尝试,我发现我可以通过juking c#generic系统来实现它.我创建了一个与插件和形状类型相反的接口,然后使用它.渲染器的分辨率由特定类型的Shape决定.Xyzzy,逆变界面使得演员不必要.
这是我可以提出的代码的最短版本作为示例.这编译并运行和行为正确:
public enum ColorDepthEnum { Color = 1, Monochrome = 2 }
public interface IRenderBinding<in TRenderer, in TData> where TRenderer : Renderer
where TData: Shape
{
void Render(TData data);
}
abstract public class Shape
{
abstract public ColorDepthEnum ColorDepth { get; }
abstract public void …
Run Code Online (Sandbox Code Playgroud) 免责声明:我知道这个例子有点荒谬; 只是想知道如果这种奇怪的情况出现的话,语言将允许我做什么.
考虑以下简短示例:
var anonymous = new
{
ToString = new Func<string>( () => { return "This came from my property.";} )
};
Console.WriteLine(anonymous);
Console.WriteLine(anonymous.ToString());
Run Code Online (Sandbox Code Playgroud)
输出有点令人惊讶:
{ ToString = System.Func`1[System.String] }
This came from my property.
Run Code Online (Sandbox Code Playgroud)
显然,当我打电话时ToString()
,c#决定
ToString
名为的属性ToString
有哪些语言结构可以让我调用ToString()
方法而不是ToString
属性的结果?
注意:我不是要覆盖ToString()
(我意识到这是不可能的),我只是想知道如何调用ToString()
而不是调用属性的返回值.
我正在测试我对另一个SO问题的回答并遇到了这种奇怪的行为,对于我的生活我不知道到底是什么.
码:
function translateLetter(input) {
const untranslated = "abcdefghijklmnopqrstuvwxyz";
const translated = "zyxwvutsrqponmlkjihgfedcba";
var i = untranslated.indexOf(input);
console.log(i);
return translated.substring(i,1);
}
console.log(translateLetter("a"));
console.log(translateLetter("b"));
console.log(translateLetter("c"));
Run Code Online (Sandbox Code Playgroud)
预期产量:
0
z
1
y
2
x
Run Code Online (Sandbox Code Playgroud)
实际产量:
0
z
1
<--- WTH?
2
y <--- WTF?
Run Code Online (Sandbox Code Playgroud)
.net ×8
c# ×8
asynchronous ×2
javascript ×2
.net-core ×1
asp.net ×1
async-await ×1
cookies ×1
delegates ×1
generics ×1
iis ×1
iis-7 ×1
interface ×1
linq ×1
outputcache ×1
performance ×1
polymorphism ×1
setinterval ×1
task ×1
wcf ×1