Lambda Expression用于语法

时间:2014-01-31 21:55:34

标签: c#

我很难理解下面的Lambda表达式。如果我没弄错了=>算术意味着去。

我有这种从xps生成pdf的方法。这个方法是否意味着运行GeneratePdf方法然后对结果变量pdf做什么?

public void GenerateCurrentPdf(FooResponse response)
{
    if (response.Success)
    {
        GeneratePdf(pdf =>
        {
            var attachInfo = new AttachmentInformation
            {
                AttachmentId = Guid.NewGuid(),
                AttachmentNote = "New Version",
                FileName = pdf.FileName,
                ImageByte = pdf.FileBytes
            };

            try
            {
                /// do something here
            }
            catch (Exception ex)
            {
                ///log error
            }
        });
    }
}

GeneratePdf方法让我更加困惑,因为它没有从调用方法传递任何参数。我在MSDN中查找Action,它说“封装了一个没有参数且不返回值的方法。”但GeneratePdf的结束再次调用GeneratePdf方法。

public void GeneratePdf(Action<FileAttachment> onComplete)
{
    string xpsPath = Environment.CurrentDirectory + "\\" + Id + ".xps";

    SaveAsXps(xpsPath, () =>
    {
        string pdfPath = Environment.CurrentDirectory + "\\" + Id + ".pdf";
        string registrationCode = ConfigurationManager.AppSettings.Get("NiXPS:RegistrationCode");
        Converter.Initialize(registrationCode);
        var outStream = new MemoryStream();
        Converter.XpsToPdf(new MemoryStream(FileToByteArray(xpsPath)), outStream);
        File.Delete(xpsPath);
        byte[] bytes = outStream.ToArray();        
        var attachment = new FileAttachment
        {
            ContentType = "application/pdf",
            FileBytes = bytes,
            FileName = fooId + ".pdf"          
        };
        onComplete(attachment);
    });
}

添加了SaveAsXps方法

private void SaveAsXps(string path, Action onComplete)
{
    Application.Current.Dispatcher.BeginInvoke(
        (Action)
            delegate
            {
                Package package = Package.Open(path, FileMode.Create);
                var xpsDoc = new XpsDocument(package, CompressionOption.Maximum);
                var xpsSm = new XpsSerializationManager(new XpsPackagingPolicy(xpsDoc), false);
                string formulaFooter = Title;
                var finalDocument = new HeaderFooterDocumentPrint(DocumentPrint, formulaFooter);
                finalDocument.ComputePageCount();
                Application.Current.Dispatcher.BeginInvoke(
                    (Action) delegate 
                    {
                        xpsSm.SaveAsXaml(finalDocument);
                        package.Close();
                        onComplete();
                    }, DispatcherPriority.SystemIdle, null);
            }, DispatcherPriority.SystemIdle, null);
}

4 个答案:

答案 0 :(得分:1)

完整的语法是(参数列表)=&gt; {方法体}

如果您只有一个参数,则可以放弃()。

如果您只想返回一个值,您可以丢弃{}并只写下结果值。

以下是等效的:

a => a + 1
(a) => a + 1
(a) => { return a+1; }

答案 1 :(得分:1)

以下代码是代表Action<FileAttachment>

的Lambda
pdf =>
    {
        // ...
    }

我会用英语说明它转换为编译器将名为pdf的参数传递给以下委托(它可以推断出类型)。

与...大致相同:

private void MyCallback(FileAttachment pdf)
{
    // ...
}

Action<T>定义为public delegate void Action<in T>(T obj);。说实话,它本质上是一个方便的内置委托定义,用于接受你告诉它的任何类型的泛型参数的void函数。

答案 2 :(得分:0)

=>并不意味着“去”。正如你所说,它是.NET的lambda语法的一部分。在这种情况下,pdf => (stuff)表示pdf是没有名称的方法的参数,=>之后的块是该方法的内容。

Action<T>是一种引用lambda的方法,该lambda接受一个参数并且不返回任何内容。

答案 3 :(得分:0)

  

这种方法是否意味着运行GeneratePdf方法,然后执行任何操作   结果变量pdf?

是。实际上,GeneratePdf可以选择不执行代码。

您可以将其视为以下内容:

public class MyCode
{
    public void MyAction(FileAttachment pdf)
    {
            var attachInfo = new AttachmentInformation
            {
                AttachmentId = Guid.NewGuid(),
                AttachmentNote = "New Version",
                FileName = pdf.FileName,
                ImageByte = pdf.FileBytes
            };

            try
            {
                /// do something here
            }
            catch (Exception ex)
            {
                ///log error
            }
    }
}


public void GeneratePdf(MyCode onComplete)
{
    string xpsPath = Environment.CurrentDirectory + "\\" + Id + ".xps";

    SaveAsXps(xpsPath, () =>
    {
        string pdfPath = Environment.CurrentDirectory + "\\" + Id + ".pdf";
        string registrationCode = ConfigurationManager.AppSettings.Get("NiXPS:RegistrationCode");
        Converter.Initialize(registrationCode);
        var outStream = new MemoryStream();
        Converter.XpsToPdf(new MemoryStream(FileToByteArray(xpsPath)), outStream);
        File.Delete(xpsPath);
        byte[] bytes = outStream.ToArray();        
        var attachment = new FileAttachment
        {
            ContentType = "application/pdf",
            FileBytes = bytes,
            FileName = fooId + ".pdf"          
        };
        onComplete.MyAction(attachment);
    });
}

public void GenerateCurrentPdf(FooResponse response)
{
    if (response.Success)
    {
        var act = new MyCode();
        GeneratePdf(act);
    }
}

这在功能上是相似的,但在时间上有一些微妙的差异。

  

GeneratePdf方法让我更加困惑,因为它没有通过   来自调用方法的任何参数。

它正在FileAttachment内的代码中接收SaveXps对象:

var attachment = new FileAttachment
{
    ContentType = "application/pdf",
    FileBytes = bytes,
    FileName = fooId + ".pdf"          
};
onComplete(attachment)

但请记住,您无法确定何时或是否会执行任何代码。 SaveXps方法通过选择是否执行传递给它的lambda代码来控制自身内部的执行,该代码引用并导致在达到onComplete(attachment)时执行外部lambda代码。