动态对象变量的 C# 索引在方法中有效,但在返回时无效,错误 C50021

Posted

技术标签:

【中文标题】动态对象变量的 C# 索引在方法中有效,但在返回时无效,错误 C50021【英文标题】:C# index to dynamic object variable works in method but not when returned, Error C50021 【发布时间】:2021-08-13 00:32:52 【问题描述】:

我有一个使用 MediaInfo.exe 从视频文件中获取信息并返回动态对象的方法。当代码运行时,方法内部的信息是可读的,但是当我返回动态对象时,它会抛出 RuntimeBinderException 并出现以下错误:

CS0021:无法将带有 [] 的索引应用于“对象”类型的表达式。

我使用以下方法调用该方法:

dynamic o = GetMediaInfoJson(filename);

我在即时窗口中键入 o["media"]["track"][1]["@type"] 并得到错误。如果我尝试使用“if”语句引用它,则会出现同样的错误。 ...

public dynamic GetMediaInfoJson(filename)

    string s = GetMediaInfoOutput(filename);  // s = json output from MediaInfo.exe
    javascriptSerializer serializer = new JavaScriptSerializer();
    dynamic o = serializer.Deserialize<dynamic>(s);

    return o;

我在即时窗口中输入 o["media"]["track"][1]["@type"] 并看到正确的值。

即返回后我“引用”o["media"]["track"][1]["@type"] 并得到错误!为什么我可以在方法内部引用动态变量,但在返回时却不能?

在 Windows Service Server 2019 上使用 Visual Studio 2019。错误是运行时错误,而不是编译时错误。

尝试最小可重现示例:

dynamic o = GetMediaInfo();


    public dynamic MediaInfoJson()
    
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string s = "\"media\": \"@ref\": \"d:\\\\inetpub\\\\ftproot\\\\slides\\\\1063_0_0_6_old.mp4\",\"track\": [\"@type\": \"general\",\"videocount\": \"1\",\"audiocount\": \"1\",\"fileextension\": \"mp4\",\"format\": \"mpeg-4\",\"format_profile\": \"base media\",\"codecid\": \"isom\",\"codecid_compatible\": \"isom/iso2/avc1/mp41\",\"vidSize\": \"9199451\",\"vidSeconds\": \"31.834\",\"overallbitrate\": \"2311856\",\"vidFrameRate\": \"30.000\",\"framecount\": \"955\",\"streamsize\": \"26218\",\"headersize\": \"40\",\"datasize\": \"9173241\",\"footersize\": \"26170\",\"isstreamable\": \"no\",\"file_created_date\": \"utc 2021-05-24 21:04:22.909\",\"file_created_date_local\": \"2021-05-24 17:04:22.909\",\"file_modified_date\": \"utc 2021-05-24 21:04:22.914\",\"file_modified_date_local\": \"2021-05-24 17:04:22.914\",\"encoded_application\": \"lavf58.45.100\",\"@type\": \"video\",\"streamorder\": \"0\",\"id\": \"1\",\"format\": \"avc\",\"format_profile\": \"high\",\"format_level\": \"3\",\"format_settings_cabac\": \"yes\",\"format_settings_refframes\": \"4\",\"codecid\": \"avc1\",\"vidSeconds\": \"31.834\",\"bitrate\": \"2177206\",\"vidWidth\": \"790\",\"vidHeight\": \"402\",\"stored_vidWidth\": \"800\",\"stored_vidHeight\": \"416\",\"sampled_vidWidth\": \"790\",\"sampled_vidHeight\": \"402\",\"pixelaspectratio\": \"1.000\",\"vidAspect\": \"1.965\",\"vidRotation\": \"0.000\",\"vidFrameRate_mode\": \"cfr\",\"vidFrameRate_mode_original\": \"vfr\",\"vidFrameRate\": \"30.000\",\"framecount\": \"955\",\"colorspace\": \"yuv\",\"chromasubsampling\": \"4:2:0\",\"bitdepth\": \"8\",\"scantype\": \"progressive\",\"streamsize\": \"8663467\",\"encoded_library\": \"x264 - core 161\",\"encoded_library_name\": \"x264\",\"encoded_library_version\": \"core 161\",\"encoded_library_settings\": \"cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=3 / lookahead_threads=1 / sliced_threads = 0 / nr = 0 / decimate = 1 / interlaced = 0 / bluray_compat = 0 / constrained_intra = 0 / bframes = 3 / b_pyramid = 2 / b_adapt = 1 / b_bias = 0 / direct = 1 / weightb = 1 / open_gop = 0 / weightp = 2 / keyint = 250 / keyint_min = 25 / scenecut = 40 / intra_refresh = 0 / rc_lookahead = 40 / rc = crf / mbtree = 1 / crf = 23.0 / qcomp = 0.60 / qpmin = 0 / qpmax = 69 / qpstep = 4 / ip_ratio = 1.40 / aq = 1:1.00\",\"extra\": \"codecconfigurationbox\": \"avcc\",\"@type\": \"audio\",\"streamorder\": \"1\",\"id\": \"2\",\"format\": \"aac\",\"format_settings_sbr\": \"no (explicit)\",\"format_additionalfeatures\": \"lc\",\"codecid\": \"mp4a-40-2\",\"vidSeconds\": \"31.781\",\"vidSeconds_lastframe\": \"-0.030\",\"bitrate_mode\": \"cbr\",\"bitrate\": \"128320\",\"channels\": \"2\",\"channelpositions\": \"front: l r\",\"channellayout\": \"l r\",\"samplesperframe\": \"1024\",\"vidAudio\": \"22050\",\"samplingcount\": \"700771\",\"vidFrameRate\": \"21.533\",\"framecount\": \"685\",\"compression_mode\": \"lossy\",\"streamsize\": \"509766\",\"streamsize_proportion\": \"0.05541\",\"default\": \"yes\",\"alternategroup\": \"1\"]";
        dynamic o = serializer.Deserialize<dynamic>(s);
        return o;
    

【问题讨论】:

您显示的代码 (((dynamic)o["media"]["track"][1]["@type"]) 不能给出 编译时间 错误。请查看问题并发布实际的minimal reproducible example。 "虽然代码已被编辑以专注于该问题,但在方法中返回 o 与调用该方法后立即出现的 Debug.Writeline 之间没有任何关系。" -- 在一个全新的 .NT 4.7.2 项目中(.NET 5 不包括 JavaScriptSerializer),使用您发布的数据和您发布的代码,它工作正常。您忽略了一些未与我们分享的重要细节。 坦率地说,这个问题是如何得到一个,更不用说 三个 在没有任何证据表明实际上有办法重现他们声称正在发生的问题的情况下,我无法理解. :( 请不要发布视频链接作为支持问题的方式。 发布实际代码。这是唯一使问题与 Stack Overflow 相关且有用的事情。如果您无法发布正确的minimal reproducible example 以可靠地重现问题,则该问题不属于该网站。 感谢您说出显而易见的彼得……整天都在努力尝试这样做……住在那座塔里一定很棒…… 【参考方案1】:

要解决此问题,我认为您需要(取决于输入的某些条件)转换为 string

dynamic o = GetMediaInfoJson(filename);
Debug.WriteLine((string)o["media"]["track"][1]["@type"] );   // Here I get the error!

大概你想用这个值做一些事情,而不是把它写到调试输出;为此,您可能仍需要转换为 string

我希望你需要在被调用的方法中做同样的事情;根据您到目前为止提供的代码,我无法解释其中的区别。

编辑:该问题现已被编辑以删除对 Debug.WriteLine() 的引用。

【讨论】:

为什么不 ToString() 这不是一回事。如果你在 dynamic 类型的对象上调用 ToString(),你仍然会有一个 dynamic。参见例如***.com/questions/41415458/… 在 WathcWindow 中查看变量内容很有用 - 从第一部分 o["media"] 然后得出结论我猜 是的,我并没有真正使用 Debug.Writline,我使用“if”语句检查它是否存在,然后使用对象的许多属性来处理视频。跨度> 好的。将来发布您正在真正使用的内容可能会很有用...!

以上是关于动态对象变量的 C# 索引在方法中有效,但在返回时无效,错误 C50021的主要内容,如果未能解决你的问题,请参考以下文章

存储过程有效,但在 c# 中给出无效列

在 C# 中,我应该按值传递参数并返回相同的变量,还是按引用传递?

C++ 库在 vb6 中有效,但在 c# 中无效

在 c# 中拥有一个采用任何类型的可索引列表的方法的最有效方法是啥

C#面向对象二

在 c# (.net core) 中使用 httpclient 时无法建立 SSL 连接,但在 Postman 和 Browser 中有效