ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 在界面中使用泛型

2019-05-16 22:54:07  阅读:281  来源: 互联网

标签:c boxing unboxing generics


更新:

海因兹是对的. AutoCAD Polyline是引用类型,而不是结构.好点子.但我简化了场景,因为我在实际应用程序中处理的是一个AutoCAD对象,它是struct.所以请将两者都视为struct而不是引用类型.

我正在寻找正确的方法来应对这种情况,如果有人能够阐明或帮助我更好地理解,我将不胜感激.

数据访问层中有一个接口,有两个实现来处理两个不同的提供程序:AutoCad和Sketchup API.

interface IEntity
{
    void object GetPoly();
    void void   InsertPoly(object poly);
}

class AutocadEntity
{
    void object GetPoly()
    {
         //calling Autocad APIs
         return Autocad Polyline object
    }
    void InsertPoly(object poly){...}
}

GetPoly的Autocad实现将返回Polyline对象,因为这是在Autocad API中定义为折线,而Sketchup将返回Face对象.

我已经将返回类型(和参数)定义为对象来处理这些不同的类型.成本是拳击/拆箱发生时的性能问题.并且它更大胆地显示返回/参数是object []的位置.

我首先想知道方法返回/参数类型泛型是解决方案,但我认为它不会是因为实现是特定于类型的.

解决方法:

尝试使用adapter pattern将PolyLine和Face类型调整为您希望使用的单一类型.例如:

public abstract class BasePoly
{
    public abstract double X { get; set; }
    public abstract double Y { get; set; }
    public abstract double Width { get; set; }
    public abstract double Height { get; set; }
}
public abstract class BasePoly<T> : BasePoly
{
    public T poly { get; private set; }
    protected BasePoly(T poly) { this.poly = poly; }
}

public class PolyLineAdapter : BasePoly<PolyLine>
{
    public PolyLineAdapter(PolyLine poly) : base(poly) {}
    // override abstracts and forward to inner PolyLine instance at 'this.poly'

    public override double X { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }

    public override double Y { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }

    public override double Width { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }

    public override double Height { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }

}

public class FaceAdapter : BasePoly<Face>
{
    public FaceAdapter(Face poly) : base(poly) {}
    // override abstracts and forward to inner Face instance at 'this.poly'

    public override double X { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }

    public override double Y { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }

    public override double Width { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }

    public override double Height { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }


}

interface IEntity
{
    BasePoly GetPoly();
    void   InsertPoly(BasePoly poly);
}

public abstract class Entity<TEntity> : IEntity
    where TEntity : BasePoly
{
    public BasePoly GetPoly()
    {
        return this.GetExternalPoly();
    }
    public abstract TEntity GetExternalPoly();
    public void InsertPoly(BasePoly poly)
    {
        this.InsertExternalPoly((TEntity) poly);
    }
    public abstract void InsertExternalPoly(TEntity poly);
}

public class AutocadEntity : Entity<PolyLineAdapter>
{
    public override PolyLineAdapter GetExternalPoly()
    {
        throw new NotImplementedException();
    }
    public override void InsertExternalPoly(PolyLineAdapter poly)
    {
        throw new NotImplementedException();
    }
}

public class SketchupEntity : Entity<FaceAdapter>
{
    public override FaceAdapter GetExternalPoly()
    {
        throw new NotImplementedException();
    }
    public override void InsertExternalPoly(FaceAdapter poly)
    {
        throw new NotImplementedException();
    }
}

// fills for third party classes
public class PolyLine {}
public class Face {}

使用adapter pattern,您提供代理层以使两个第三方类型符合您要使用的类型.

请记住,此设计假设您一次只能使用一种类型的第三方引擎.如果您将同时使用两个引擎,请进行以下更改:

public class BasePoly
{
    public double X { get; set; }
    public double Y { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
}

interface IEntity
{
    BasePoly GetPoly();
    void InsertPoly(BasePoly poly);
}

public abstract class Entity : IEntity
{
    public abstract BasePoly GetPoly();
    public abstract void InsertPoly(BasePoly poly);
}

public class AutocadEntity : Entity
{
    public override BasePoly GetPoly()
    {
        // retrieve external type, convert it to BasePoly and return that
        throw new NotImplementedException();
    }
    public override void InsertPoly(BasePoly poly)
    {
        // convert BasePoly to external type and insert that
        throw new NotImplementedException();
    }
}

public class SketchupEntity : Entity
{
    public override BasePoly GetPoly()
    {
        // retrieve external type, convert it to BasePoly and return that
        throw new NotImplementedException();
    }
    public override void InsertPoly(BasePoly poly)
    {
        // convert BasePoly to external type and insert that
        throw new NotImplementedException();
    }

}

// fills for third party classes
public class PolyLine {}
public class Face {}

此外,如果您担心适配器装箱或转换操作的成本(在您实际测量并确定是否需要优化之前我不会这样做),那么您可以将适配器模式应用于使用IEntity的调用者而不是PolyLineAdapter / FaceAdapter或AutocadEntity / SketchupEntity类型本身.基本上,构建一个插件引擎.您可以使用泛型来抽象两个实现之间的常见习语.

这是一个dotnetfiddle示例:https://dotnetfiddle.net/UsFPM7

标签:c,boxing,unboxing,generics
来源: https://codeday.me/bug/20190516/1117093.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有