(C#) 为什么 Visual Studio 说它是一个对象,而 GetType 说它是一个 Func
2023-12-08

C#新手问题在这里。以下代码(摘自 Apress 的 Christian Gross 所著的《C# From Novice to Professional》一书)给出了错误:

worksheet.Add("C3", CellFactories.DoAdd(worksheet["A2"], worksheet["B1"]));

原因是方法DoAdd()不接受给定的参数。

public static Func<object> DoAdd(Func<object> cell1, Func<object> cell2) {...}

VS 声称上面方法调用中的两个参数都是类型object而该方法只接受Func<object>。但是value两个工作表元素的类型都是Func<object>:

worksheet.Add("A2", CellFactories.Static(10.0));

在哪里这个Static方法只返回给定值:

public static Func<object> Static(object value) { return () => value; }
// return type= Func<object>

当我施放时worksheet["A2"] as Func<object>,代码确实有效。

但有件事我不明白。对象实例的类型是Func<object>。我已经用过GetType()方法来查看证明,并将原始元素的对象类型与转换对象的对象类型(已接受)进行比较:

Console.Writeline(worksheet["A2"].GetType());

// now cast to the correct type (why can't it do that implicitly, btw?)
Funk1 = worksheet["A2"] as Func<object>;

Console.Writeline(Funk1.GetType());

..而且它们都是相同的! (类型=System.Func'1[System.Object])

即使当我使用.Equals()方法比较两种类型,它返回true.

然而,VS 将第一个对象实例视为类型object在方法调用中。为什么?为什么被调用的方法将参数“视为”与 GetType() 返回的类型不同的类型? (如果是这样,那有什么好处GetType()方法?)

非常感谢您的建议/评论! (如果书上的例子给出了错误,而你看不到原因,那么学习这门语言就有点困难了——因此,有一种模糊的印象,认为有问题GetType() or VS.)


您需要了解之间的区别动态类型 and 静态类型。适合您的索引器worksheet对象最有可能具有静态类型object.

public object this[string cell]{get{...}set{...}}

因为C#中的所有对象inherit从类型object,存储在单元格中的对象引用可以是对any object.

也就是说,因为委托(例如Func<T>) is an object,它可以存储在object参考:

Func<object> func = ()=>return "foo";
object o = func; // this compiles fine

编译器可以解决这一切,因为它隐式地理解派生类可以存储在对基类的引用中。

编译器无法自动执行的操作是确定动态类型,或者运行时类型一个物体的是。

Func<object> func = ()=>return "foo";
object o = func; // this compiles fine
func = o; // <-- ERROR

编译器不知道object存储在o实际上是类型Func<object>。它不应该跟踪这一点。这是必须在运行时检查的信息。

func = (Func<object>)o; // ok!

上面的代码行编译后的行为与此类似:

if(o == null)
    func = null;
else if(typeof(Func<object>).IsAssignableFrom(func.GetType()))
    __copy_reference_address__(func, o); // made up function!  demonstration only
else throw new InvalidCastException();

通过这种方式,可以在运行时检查任何强制转换(从一种类型到另一种类型的转换),以确保其有效且安全。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(C#) 为什么 Visual Studio 说它是一个对象,而 GetType 说它是一个 Func? 的相关文章
  • 在动态事件处理程序中引用“this”

    在我的 myClass 类中 我使用 Reflection Emit 为 myClass 类成员之一动态编写事件处理程序 我已经成功地做到了这一点 现在 我想修改事件处理程序以调用 myClass 类中的实例方法之一 但是 我无法弄清楚如何
  • 获取 std::variant 当前持有的 typeid(如 boost::variant type())

    我已经从 boost variant 迁移到 std variant 但遇到了障碍 我在 boost type 中使用了一个很好的函数 它可以让你获取当前持有的 typeid 看https www boost org doc libs 1
  • 键盘加速器在 UWP 应用中停止工作

    我正在尝试将键盘加速器添加到 UWP 应用程序中的 CommandBar 菜单项 当应用程序启动时 这工作正常 但在我第一次打开溢出菜单后 加速器停止工作 这似乎不会发生在主要命令 菜单之外 上 只有溢出菜单内的辅助命令才会发生 此外 单击
  • 从 future 中检索值时的 SIGABRT

    我在使用 C 11 future 时遇到问题 当我打电话时wait or get 关于返回的未来std async 程序接收从mutex标头 可能是什么问题呢 如何修复它 我在 Linux 上使用 g 4 6 将以下代码粘贴到 ideone
  • 方法“xxx”不能是事件的方法,因为该类派生的类已经定义了该方法

    我有一个代码 public class Layout UserControl protected void DisplayX DisplayClicked object sender DisplayEventArgs e CurrentDi
  • 是否有像 gccxml 这样的用于生成包装器的 C 标头解析器工具?

    我需要为一种新的编程语言编写一些 C 标头包装器 并且想要类似 gccxml 的东西 但不完全依赖 gcc 以及它在 Windows 系统上带来的问题 只需要读C而不是C 只要有完整的文档记录 任何格式的输出都可以 Linux Solari
  • 在 MATLAB 中创建共享库

    一位研究人员在 MATLAB 中创建了一个小型仿真 我们希望其他人也能使用它 我的计划是进行模拟 清理一些东西并将其变成一组函数 然后我打算将其编译成C库并使用SWIG https en wikipedia org wiki SWIG创建一
  • 指向字节数组的指针

    由于 Misra C 的要求 我的一位同事想要使用指针声明 但我遇到了一些问题 Misra 安全关键指南 不会让我们纯粹的程序员使用指针 但会让我们对数组字节进行操作 他打算获取一个指向字节数组的指针 因此我们不会在堆栈上传递实际的数组 T
  • 编译器错误“错误:在文件范围内可变地修改了‘字符串’”

    考虑 include
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • dropdownlist DataTextField 由属性组成?

    有没有一种方法可以通过 C 使 asp net 中的下拉列表的 datatextfield 属性由对象的多个属性组成 public class MyObject public int Id get set public string Nam
  • 错误左值需要作为赋值C++的左操作数

    整个程序基本上只允许用户移动光标 如果用户位于给定的坐标范围 2 2 内 则允许用户键入输入 我刚刚提供了一些我认为足以解决问题的代码 我不知道是什么导致了这个问题 你能解释一下为什么会发生吗 void goToXY int int 创建一
  • 正确使用“extern”关键字

    有一些来源 书籍 在线材料 解释了extern如下 extern int i declaration has extern int i 1 definition specified by the absence of extern 并且有支
  • 设计 Javascript 前端 <-> C++ 后端通信

    在我最近的将来 我将不得不制作一个具有 C 后端和 Web 前端的系统 要求 目前 我对此了解不多 我认为前端将触发数据传输 而不是后端 所以不需要类似 Comet 的东西 由于在该领域的经验可能很少 我非常感谢您对我所做的设计决策的评论
  • 从 C 线程调用 Python 代码

    我对从 C 或 C 线程调用 Python 代码时如何确保线程安全感到非常困惑 The Python 文档 http docs python org c api init html non python created threads似乎是
  • 如何将对象转换为传递给函数的类型?

    这不会编译 但我想做的只是将对象转换为传递给函数的 t public void My Func Object input Type t t object ab TypeDescriptor GetConverter t ConvertFro
  • 如何设置 CMake 与 clang 交叉编译 Windows 上的 ARM 嵌入式系统?

    我正在尝试生成 Ninja makefile 以使用 Clang 为 ARM Cortex A5 CPU 交叉编译 C 项目 我为 CMake 创建了一个工具链文件 但似乎存在错误或缺少一些我无法找到的东西 当使用下面的工具链文件调用 CM
  • C# 粘贴到文本框时检查剪贴板中的字符

    有没有一些方法可以在粘贴到文本框 C 之前仅检查剪贴板中的字符 Ctrl V 和右键单击 gt 粘贴 但不使用 MaskedTextbox 在文本框文本更改中添加规则以仅接受数字 例如 private string value privat
  • 启动画面后主窗口出现在其他窗口后面

    我有一个带有启动屏幕的 Windows 窗体应用程序 当我运行该应用程序时 启动屏幕显示正常 消失并加载应用程序的主窗体 但是 当我加载主窗体时 它出现在包含该应用程序的 Windows 资源管理器目录下 这是运行启动画面然后运行主窗体的代
  • 新的 .NET 6 控制台模板中的 C# 函数重载不起作用

    我在尝试重载该函数时遇到错误Print object in the 新的 NET 6 C 控制台应用程序模板 https learn microsoft com en us dotnet core tutorials top level t

随机推荐