testit()方法是一个闭包.aString已超出范围,但testit()仍然可以在其上执行.testit2()使用的是一个没有超出范围(mystring)的变量,但是它也没有传递给testit2().testit2()被认为是封闭吗?
string mystring = "hello world";
Action testit = new Action(delegate { string aString = "in anon method"; Debug.WriteLine(aString); });
testit();
//capture mystring. Is this still a closure?
Action testit2 = new Action(delegate { Debug.WriteLine(mystring); });
//mystring is still in scope
testit2();
Run Code Online (Sandbox Code Playgroud)
在第二个示例中,mystring可以在方法之外更新,这些更改将反映在testit2()中.这不像普通方法,只能捕获mystring作为参数.
今天我在VB.NET中目睹了一些非常奇怪的行为.我正在谈论的代码如下:
Option Strict On
Option Explicit On
Module Module1
Sub Main()
Dim thisShouldBeSet = False
DoSomething(Function() thisShouldBeSet = True)
If Not thisShouldBeSet Then
Throw New Exception()
End If
Console.WriteLine("yaay")
End Sub
Sub DoSomething(action As Action)
action.Invoke()
End Sub
End Module
Run Code Online (Sandbox Code Playgroud)
我知道代码本身存在缺陷,因为我必须使用:
DoSomething(Sub() thisShouldBeSet = True)
Run Code Online (Sandbox Code Playgroud)
代替:
DoSomething(Function() thisShouldBeSet = True)
Run Code Online (Sandbox Code Playgroud)
但我觉得很奇怪,即使使用Option Strict和Option Explicit,编译也允许我编译这段代码.
更奇怪的是,在运行代码时,Action实际上表现得像一个Func(布尔值).
任何人都可以向我提供有效解释为什么在VB.NET中允许这样做?这是编译器/运行时错误吗?
我有一个视图,它返回一个包含多个页面的pdf(使用iTextSharp),但现在我必须更改它,以便每个页面都是一个单独的pdf(带有它自己的唯一标题)并返回一个zip文件.
我的原始代码如下所示:
public FileStreamResult DownloadPDF()
{
MemoryStream workStream = new MemoryStream();
Document document = new Document();
PdfWriter.GetInstance(document, workStream).CloseStream = false;
document.Open();
// Populate pdf items
document.Close();
byte[] byteInfo = workStream.ToArray();
workStream.Write(byteInfo, 0, byteInfo.Length);
workStream.Position = 0;
FileStreamResult fileResult = new FileStreamResult(workStream, "application/pdf");
fileResult.FileDownloadName = "fileName";
return fileResult;
}
Run Code Online (Sandbox Code Playgroud)
使用gzip压缩文件看起来很简单,但我不知道如何gzip多个文件并将其作为一个zip文件返回.或者我应该使用gzip以外的东西,比如dotnetzip或sharpzip?
提前致谢!
本周我参加了荷兰的TechDays 2013,我得到了一个有趣的测验问题.问题是:以下程序的输出是什么.这是代码的样子.
class Program
{
delegate void Writer();
static void Main(string[] args)
{
var writers = new List<Writer>();
for (int i = 0; i < 10; i++)
{
writers.Add(delegate { Console.WriteLine(i); });
}
foreach (Writer writer in writers)
{
writer();
}
}
}
Run Code Online (Sandbox Code Playgroud)
显然,我给出的答案是错误的.我认为,因为int是一个值类型,传递的实际值Console.WriteLine()被复制,所以输出将是0 ... 9.但是i在这种情况下作为参考类型处理.正确答案是它会显示十次10.有人可以解释为什么以及如何解释?
我浏览了一些 C# 示例并发现了以下内容:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
delegate void Printer();
static void Main()
{
List<Printer> printers = new List<Printer>();
for (int i = 0; i < 10; i++)
{
printers.Add(delegate { var d = i; Console.WriteLine(d); });
}
foreach (var printer in printers)
{
printer();
}
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我期望它0通过输出9,因为 anint是一种值类型,d应该设置为i当时的任何值。
然而,这输出了10十倍。
为什么是这样?int 不是一个引用而是在委托内部吗?
注意:我并不是想在这里解决问题,只是以可重复应用的方式了解它是如何工作的。
编辑:我的困惑的例子
int i = …Run Code Online (Sandbox Code Playgroud) 这里是JustDecompile反编译的一个ASP.NET Core nuget包,我看不懂<>c.<>9. 我发现他们没有声明,很奇怪,Nuget包名是Microsoft.Extensions.FileProviders.Physical,类文件名是PhysicalFilesWatcher.
匿名方法是否内联定义?在下面的示例中,委托对象"d"引用了匿名方法,该方法访问Fun方法中定义的"x"变量."x"的范围应限于Fun方法,但是当我们调用MyFun时,它会调用作为参数传递的委托并递增"x"的值.
输出结果是"6",这是怎么发生的?在匿名方法中,"x"的值或首先是"x"变量本身的值是多少?
public delegate void Del();
public void Fun()
{
int x = 5;
Del d = delegate { x++; };
MyFun(d);
Console.WriteLine(x);
}
public static void MyFun(Del d)
{
d();
}
Run Code Online (Sandbox Code Playgroud) 我一直试图解决这个问题,这真的让我烦恼.我有一些看起来像这样的代码
static T MyFunction<T>(Func<T> action, int i, int i2)
{
...some code here
}
Run Code Online (Sandbox Code Playgroud)
当我需要调用此代码时,我尝试了这个
var result = MyFunction<List<string>>(MethodThatReturnsListofString(int number), 1,2)
Run Code Online (Sandbox Code Playgroud)
它失败说明最佳重载具有无效参数但是当我尝试以下操作时
var result = MyFunction<List<string>>(() => MethodThatReturnsListofString(int number), 1,2)
Run Code Online (Sandbox Code Playgroud)
它工作正常.在这种情况下,"()=>"的功能是什么.我认为()不能用于需要超过0 args的方法.
我在.NET中设计win表单时使用过代理...即拖放按钮,双击,然后填写myButton_click事件.我想了解如何在C#中创建和使用用户定义的委托.
如何在C#中使用和创建用户定义的委托?
我想做的是以下几点:
我有一个CefSharp ChromiumWebBrowser(WPF控件),我想在该浏览器中截取网页的屏幕截图。屏幕ChromiumWebBrowser上没有获取屏幕截图的方法。但是我可以通过将事件处理程序附加到OnPaint浏览器的事件来获取渲染。这样,我得到的位图就是屏幕截图。该过程基于以下答案:https : //stackoverflow.com/a/54236602/2190492
现在,我正在创建一个类CefSharpScreenshotRecorder,该类负责拍摄屏幕截图。它应该接受浏览器实例,将事件处理程序附加到OnPaint事件,并获取位图。该过程的所有状态都应封装在CefSharpScreenshotRecorder该类中。我希望能够异步使用我的课程。因为我们必须等到OnPaint事件被触发。触发该事件(并调用事件处理程序)后,该事件处理程序中将提供一个位图。然后,该位图应该是最初调用的异步方法的结果(如CefSharpScreenshotRecorder.TakeScreenshot(...cefBrowserInstance...)。当然,所有事情都必须在不阻塞/滞后UI的情况下发生。
我对C#中的异步编程不是很熟悉。我遇到的问题是,我找不到找到一种可以等待的方法的方法,该方法仅在被调用时代表OnPaint事件处理程序返回。我什至不知道是否存在任何代码功能来创建此逻辑。
我尝试了这段代码
struct Bar {
public int Value;
}
async Task doItLater(Action fn) {
await Task.Delay(100);
fn();
}
void Main() {
Bar bar = new Bar { Value = 1 }; //Bar is a struct
doItLater(() => {
Console.WriteLine(bar.Value);
}).Wait();
}
Run Code Online (Sandbox Code Playgroud)
得到了输出1.现在这让我很困惑.我的逻辑如下
Task.Delay(100)命中时,该执行线程完成,并且请求TPL fn()稍后执行.bar 存储在堆栈上,当我们在闭包中访问它时,该帧不应该存在.那么我怎么得到一个输出1?
c# ×11
.net ×4
delegates ×4
closures ×2
asp.net-core ×1
async-await ×1
cefsharp ×1
decompiling ×1
file ×1
function ×1
itextsharp ×1
lambda ×1
linq ×1
scope ×1
screenshot ×1
struct ×1
value-type ×1
vb.net ×1
wpf ×1
zip ×1