【问题标题】:Reinterpret cast in C# , how?重新解释 C# 中的演员阵容,如何?
【发布时间】:2013-10-02 09:34:18
【问题描述】:

我已经定义了这样一个函数:

public static void WriteResponse(ref HttpContext ctx, object sender, Type typeName)
{
    var model = sender as typeName; // it's an error-line, becase of `as typeName`
    var jsonObject = new JavaScriptSerializer().Serialize(model);
    ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
    ctx.Response.ContentType = "Content-type: application/json";
    ctx.Response.ContentEncoding = Encoding.UTF8;
    ctx.Response.Write(jsonObject);
}

如您所见,它甚至无法编译,因为以下行:

var model = sender as typeName;

我从那个调用这个函数:

internal void GetShortInfo(ref HttpContext ctx, ref Shapefile shapefile)
{
    var model = new Models.SfShortInfo()
    {
        Count = shapefile.Count,
        Type = shapefile.Type.ToString()
    };

    ShapefileService.WriteResponse(ref ctx, (object)model, model.GetType());
}

还有这样的电话:

ShapefileService.WriteResponse(ref ctx, (object)model, model.GetType());

我想从自己设计的 API Web 服务中添加任何功能。

我想,你有一个想法,我正在尝试什么TO DO

我想定义一个函数,它可以通过将模型实例装箱到 System.Object 并为 JSON 响应拆箱来接受来自各种数量的其他函数的调用。

类似于 C++ 中的reinterpret_cast<> 函数。我认为,我可以使用 Generics 在 C# 中完成它,但我不太了解 C# 的那部分,所以我建议您提供帮助。

谢谢!

【问题讨论】:

  • 我认为您拼错了“为什么?”在问题标题中
  • 公平地说,这个标题对于 C++ 程序员来说有点奇怪(我们拥有reinterpret-cast标签的权利)
  • @sehe 你为什么这么认为?
  • 这完全不像我书中的reinterpret_cast。更像dynamic_cast
  • 你为什么还要尝试提出论点?据我所知,Serialize 方法采用 object...

标签: c# templates generics boxing reinterpret-cast


【解决方案1】:

通常的方法是静态多态:

public static void WriteResponse<T>(ref HttpContext ctx, object sender) 
    where T : class
{
    var model = sender as T;

    // ...
}

where T : class 因为T 需要是引用类型AFAIR。如果不需要,切换到“硬”演员:

    var model = (T) sender;

或者,您可以使整个演员表隐含(感谢@Aik 指出)

public static void WriteResponse<T>(ref HttpContext ctx, T model) 
{
    // ...
}

【讨论】:

  • 为什么不在方法签名中使用 T 而不是 object?那时就不需要演员表了。
  • @C.B.感谢您的修复。它被拒绝了,但我仍然得到它。是的,我曾考虑过扔掉旧的签名,但我无法再理解关于 ref 与 value 类型的观点了。 :( 我认为现在一切都很好。
【解决方案2】:

你根本不需要演员表。 JavaScriptSerializer.Serialize 方法有这个原型:

public string Serialize(Object obj)

这意味着您的“未装箱”模型将再次装箱,而您不必这样做。该函数在内部使用反射并且能够读取所有模型元数据,即使它作为对象传递给方法。

对于HttpContext 使用ref 是不必要的,这有点危险,因为HttpContext 是引用类型,您可以在被调用的方法中更改引用。我从未见过使用 ref 关键字传递引用类型的充分理由。它主要用于值类型。

您的解决方案可能如下所示:

public static void WriteResponse(HttpContext ctx, object model)
{
    string jsonObject = new JavaScriptSerializer().Serialize(model);
    ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
    ctx.Response.ContentType = "Content-type: application/json";
    ctx.Response.ContentEncoding = Encoding.UTF8;
    ctx.Response.Write(jsonObject);
}

第二点是你不必将模型转换为object,你可以直接传递模型:

ShapefileService.WriteResponse(ctx, model);

如果您确实需要在WriteResponse 方法中使用强类型,则可以使用泛型方法:

public static void WriteResponse<T>(HttpContext ctx, T model)
{
    string jsonObject = new JavaScriptSerializer().Serialize(model);
    ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
    ctx.Response.ContentType = "Content-type: application/json";
    ctx.Response.ContentEncoding = Encoding.UTF8;
    ctx.Response.Write(jsonObject);
}

ShapefileService.WriteResponse<Models.SfShortInfo>(ctx, model);

【讨论】:

    【解决方案3】:

    这是一个不能解决但要避免的问题。事实上,将模型转换为一种类型或另一种类型是无用,因为当你将它传递给Serialize时,它会再次变成一个对象。

    只需从您的代码中完全删除这一行:

    var model = sender as typeName;
    

    JavaScriptSerializer 会处理所有细节。

    【讨论】:

    • +1 我以为演员阵容有一些外部需求,但未显示
    【解决方案4】:

    通过在 C# 中使用泛型,您可以这样编写代码:

    public static void WriteResponse<T>(HttpContext ctx, T sender)
    {
        var jsonObject = new JavaScriptSerializer().Serialize(sender);
        ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
        ctx.Response.ContentType = "Content-type: application/json";
        ctx.Response.ContentEncoding = Encoding.UTF8;
        ctx.Response.Write(jsonObject);
    }
    
    internal void GetShortInfo(HttpContext ctx, Shapefile shapefile)
    {
        var model = new Models.SfShortInfo
        {
            Count = shaefile.Count,
            Type = shapefile.Type.ToString()
        };
    
        ShapefileService.WriteResponse(ctx, model);
    }
    

    这样就不需要进行任何强制转换,因为它会作为它已经需要知道的类型进入函数。

    【讨论】:

      【解决方案5】:

      这会起作用..但您应该知道,这比您可能期望的更安全(假设您提出reinterpret_cast):

       var model = Convert.ChangeType(sender, typeName);
      

      如果您只是要随机抛出类型,则可能会抛出异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-05
        • 1970-01-01
        相关资源
        最近更新 更多