在任务运行中的 lambda 中出现返回类型的奇怪编译器错误

问题描述 投票:0回答:2

我有以下方法:

    public Task<List<T>?> ReadXmlAsync<T>(IEnumerable<string> xmlFileEntries)
    {
        return Task.Run(() =>
        {
            var xmlDtos = new List<T>();
            var serializer = new XmlSerializer(typeof(T));

            foreach (var xml in xmlFileEntries)
            {
                using var fs = new FileStream(xml, FileMode.Open);

                if (serializer.Deserialize(fs) is not T dto)
                    return null;

                xmlDtos.Add(dto);
            }

            return xmlDtos;
        });
    }

它读取

xmlFileEntries
中的 xml 文件 frpm 路径,尝试反序列化它们,如果任何反序列化失败或反序列化集合
xmlDtos
,则返回 null。如果我想扩展它的功能,并且不仅在反序列化失败时返回 null,而且还返回损坏的 xml 文件的路径(变量称为
xml
),那么我的方法应该看起来像这样:

    public Task<(List<T>?, string?)> ReadXmlAsync<T>(IEnumerable<string> xmlFileEntries)
    {
        return Task.Run(() =>
        {
            var xmlDtos = new List<T>();
            var serializer = new XmlSerializer(typeof(T));

            foreach (var xml in xmlFileEntries)
            {
                using var fs = new FileStream(xml, FileMode.Open);

                if (serializer.Deserialize(fs) is not T dto)
                    return (null, xml);

                xmlDtos.Add(dto);
            }

            return (xmlDtos, null);
        });
    }

但它不起作用,编译器强调

return (null, xml);
return (xmlDtos, null);
return
关键字上抛出 CS8030:

CS8030: Anonymous function converted to a void returning delegate cannot return a value.

CS8135 和 CS1662 在一个元组上:

CS8135: Tuple with 2 elements cannot be converted to type 'object'

但是如果我不返回 null 而不是字符串(将

return (xmlDtos, null);
替换为例如
return (xmlDtos, string.Empty);
),编译器将停止给出错误。我究竟做错了什么?可能是我不明白 lambda 是如何正确工作的?

c# task task-parallel-library
2个回答
1
投票

Task.Run
可以采用几种不同类型的委托参数,编译器很难确定您要传递给它的类型。您可以通过执行以下一项或多项操作来帮助它:

  • 在返回类型中转换
    null
    return (xmlDtos, (string?) null);
  • 为 Task.Run 提供显式泛型类型:
    Task.Run<(List<T>?, string?)>(...)

0
投票

为什么将非异步功能包装在任务中?只要使这个方法异步,那么你就不需要 Task.Run。

public Task<(List<T>?, string?)> ReadXmlAsync<T>(IEnumerable<string> xmlFileEntries)
{
    var xmlDtos = new List<T>();
    var serializer = new XmlSerializer(typeof(T));

    foreach (var xml in xmlFileEntries)
    {
        using var fs = new FileStream(xml, FileMode.Open);

        if (serializer.Deserialize(fs) is not T dto)
            return Task.FromResult((default(List<T>), xml));

        xmlDtos.Add(dto);
    }

    return Task.FromResult((xmlDtos, default(string)));

https://dotnetfiddle.net/vfeZpE

© www.soinside.com 2019 - 2024. All rights reserved.