【问题标题】:C# alternative to VB codeC# 替代 VB 代码
【发布时间】:2016-07-22 08:05:57
【问题描述】:

我有这个 VB 代码

 Public Function InitMeridDataType() As MeridDataType
        Dim OutData As MeridDataType
        With OutData
            .NumCurves = 0
            Erase .CurveData
        End With
        Return OutData
    End Function

我使用Telerik Online Tool将此代码转换为C#

C#代码是

 public static MeridDataType InitMeridDataType()
        {
            MeridDataType OutData = default(MeridDataType);
            var _with1 = OutData;
            _with1.NumCurves = 0;
            _with1.CurveData = null;
            return OutData;
        }

MeridDataType 在 VB 中定义为

Public Structure MeridDataType
        Dim NumCurves As Short
        Dim CurveData() As CurveDataType
    End Structure

我觉得 C# 代码存在严重问题。它不应该返回 _with1 吗?

我写的一个版本是

public static MeridDataType InitMeridDataType()
            {
                MeridDataType OutData = default(MeridDataType);
                //var _with1 = OutData;
                OutData .NumCurves = 0;
                OutData .CurveData = null;
                return OutData;
            }

有什么线索吗?

【问题讨论】:

  • 我找不到任何使这段代码有意义的结构。如果MeridDataType 是引用类型,则此代码应始终生成NullReferenceException。如果MeridDataType 是值类型,那么原始With 块应该已被编译器拒绝,因为您只能读取 成员并调用此类With 块中的方法。跨度>
  • @Damien_The_Unbeliever 我同意。一些简单的测试表明,上述工具并不关心代码的(语义)有效性。它会愉快地转换导致 NRE 的代码而不会出现问题。所以,我猜原来的 VB.NET 代码也有“问题”,它们是“正确”转换的 ;-)
  • 整个方法在c#中是没有意义的,这是结构的默认构造函数无论如何都会做的。
  • 一分钱一分货。无论如何它都会起作用。

标签: c# vb.net winforms


【解决方案1】:

我觉得 C# 代码有严重问题。

我同意。 MeridDataType 被定义为值类型,因此尝试通过复制 _with1 修改 OutData 不会达到预期效果:将返回未修改的 OutData

如果您只需要在数据对象上设置一些属性,这与 C# 中的操作一样简单:

public static MeridDataType InitMeridDataType()
{
   return new MeridDataType()  // the parentheses are actually optional
   {
       NumCurves = 0,
       CurveData = null
   };
}

(顺便说一句:将NumCurvesCurveData显式设置为“空值”实际上并不是必需的。这已经通过默认构造函数隐式完成,它将底层内存初始化为“全零”,因此重置这些属性没有额外的影响!不过,这可能是个好主意,因为它明确了你的值应该被初始化为什么。)


P.S.:new T()default(T)?

TL;DR:使用 new T(…) 创建 T 实例,而不是 default(T)... 即使是 structs。

通过new T() 正确地获取某种类型T 的新实例。与 default(T) 不同,这清楚地表明了您的意图,并且始终按照您的意愿行事:

  • 仅对于值类型 (structs),C# 的 default(T) 等效于 new T() 默认构造函数:两者都为您提供具有其底层内存初始化为“全零”。但这是一种创建新实例的偷偷摸摸的方式,而且不是很透明。在您不知道实际类型 T 的情况下,最好保留使用 default(T),例如在泛型方法中。

  • 对于引用类型(例如classinterface),default(T) 将返回一个null 引用,因此随后访问T 将产生异常。

【讨论】:

  • 谢谢 :) 但是@Kurakura88 提到的方式也可以吗?
  • @Apoorv,是的,Kurakura88 建议的方式也可以。
【解决方案2】:

参考默认值:https://msdn.microsoft.com/en-us/library/xwth0h0d.aspx。 如果 MeridDataType 是一个结构,那么您的代码应该可以正常工作。如果是类,最好用默认构造函数实例化。

public static MeridDataType InitMeridDataType()
{
   MeridDataType OutData = new MeridDataType();
   OutData.NumCurves = 0;
   OutData.CurveData = null;
   return OutData;
}

【讨论】:

  • 假设 VB.NET 代码在逻辑上是正确的并且没有错误,看来MeridDataType 将是一个值类型(struct),所以default(MeridDataType) 不等于null。它等于 MeridDataType,其底层内存位已清零。
  • 我相信你的话
  • @kurakura88 MeridDataType 是一个 struct 。你能仔细检查一下,让我知道我是否可以继续使用 Default 吗?
  • 默认应该没问题,只要是结构体就行了
  • @Apoorv:如果MeridDataType是值类型(struct),default(MeridDataType)等价于new MeridDataType(),但这不是一个好主意。请改用更明确的new MeridDataType()。在new T() 不可用的情况下保留default(T),例如在您不知道T 可能是什么的通用方法中。
【解决方案3】:

OutData 和 _with1 是同一个对象,所以它确实与你返回的不匹配。

【讨论】:

  • 正如我在评论中所说,我无法理解这种结构。 如果 MeridDataType 是引用类型,则该变量被有效地分配null(通过default),然后设置其NumCurves 属性 - 这应该始终生成异常。
  • @Damien_The_Unbeliever 我不知道如何解决问题。你想让我用默认值做什么?我应该删除它并使用新的运营商吗?据我了解,默认将元素初始化为其初始值
  • Neil : OutData_with1 不是同一个对象,因为 MediaDataType 是一个值类型(Structure)。这一行:var _with1 = OutData;OutData 做了一个浅拷贝,这意味着我们现在有两个不同的结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多