仅与内部实现接口

发布于 2025-02-08 18:18:14 字数 659 浏览 1 评论 0 原文

我目前正在编写一个以QOI格式编码和解码图像的库。此图像格式使用RGB和RGBA像素格式。

我制作了 ipixel 接口和两个实现 rgbpixel rgbapixel ipixel 不打算用作扩展点(因为只有RGB和RGBA),我使此接口使用通用类,以免两次编写相同的内容。

rgbpixel rgbapixel [structlayout] 属性的结构。我的某些通用类使用不安全的代码来不安全地施放这些结构和其他非托管类型以提高性能,因此,如果用户/另一个实现 ipixel 触发了他们,则很可能会导致例外。

为了避免所有这些问题,我想仅允许内部实现 ipixel 接口。但是我不知道该如何在C#。中执行此操作,

如果 ipixel 是一个抽象类,我可以通过仅具有内部构造函数来防止其他组件实现。但是我只能使用接口,因为我需要 rgbpixel rgbapixel 是structs。

.netstandart 2.0,C#10.0

I am currently writing a library that encodes and decodes images in qoi format. This image format uses rgb and rgba pixel formats.

I made the IPixel interface and two implementations RgbPixel and RgbaPixel. IPixel is not intended to be used as an extension point (because there are only rgb and rgba), I made this interface to use generic classes so as not to write the same thing twice.

RgbPixel and RgbaPixel are structs with the [StructLayout] attribute. Some of my generic classes use unsafe code to unsafely cast these structs and other unmanaged types to each other to improve performance, so if user/another implementation of IPixel gets to them, it will most likely cause an exception.

To avoid all these problems, I would like to allow only internal implementation of the IPixel interface. But I don't know how to do it in C#.

If IPixel were an abstract class, I could prevent implementation from other assemblies by having only internal constructors. But I can only use interfaces because I need RgbPixel and RgbaPixel to be structs.

.netstandart 2.0, c# 10.0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小草泠泠 2025-02-15 18:18:14

我会制作 ipixel 内部,并具有接受 rgbpixel rgbapixel 的公共垫子方法,然后调用接受 ipixel ipixel的通用方法代码>(或基类)。

I would make IPixel internal and have public shim methods that accept RgbPixel and RgbaPixel which then call the common method that accepts IPixel (or a base class).

木緿 2025-02-15 18:18:14

我使所有类构造函数内部进行了内部,并添加了两种静态方法 load new< t> ,第一个使用一个编码的数据,并通过解码标头来创建 qimage< rgbpixel> qimage< rgbapixel> ,第二种方法仅检查用户传递的类型参数,如柯克·沃尔(Kirk Woll)在注释中所建议的。

看起来像这样:


public class QImage : IImage {
internal QImage(/*args*/) { /*...*/ }

public static QImage Load(byte[] bytes) {
    //...

    var qr = new QoiBytesReader(bytes);
    var qHeader = Decoder.DecodeHeader(ref qr);

    //ugly :|
    return qHeader.Channels == Channels.Rgb 
         ? new QImage<RgbPixel>(Decoder.DecodePixels<RgbPixel>(ref qr, in qHeader), qHeader) 
         : new QImage<RgbaPixel>(Decoder.DecodePixels<RgbaPixel>(ref qr, in qHeader), qHeader);
    }

//...
}

public class QImage<T> : QImage where T : unmanaged, IPixel {
    internal QImage(/*args*/) : base(/*params*/) { /*...*/ }

public static QImage<T> New(byte[] pixels, QHeader qHeader) {
    if (typeof(T) == typeof(RgbPixel) || typeof(T) == typeof(RgbaPixel)) 
        return new QImage<T>(pixels, qHeader);
        
    throw new NotSupportedException($"Specified type <{typeof(T).Name}> is not supported. Use <{nameof(RgbPixel)}> or <{nameof(RgbaPixel)}> instead.");
    }
//...
}

internal static unsafe class Decoder {
internal static byte[] DecodePixels<T>(ref QoiBytesReader qr, in QHeader metadata) 
    where T : unmanaged, IPixel { /*decode*/ }

//...
}

I made all the class constructors internal and added two static methods Load and New<T>, the first one takes an encoded data and by decoding the header it creates either QImage<RgbPixel> or QImage<RgbaPixel>, the second method merely checks the type parameter passed by the user, as suggested by Kirk Woll in the comments.

Looks something like this:


public class QImage : IImage {
internal QImage(/*args*/) { /*...*/ }

public static QImage Load(byte[] bytes) {
    //...

    var qr = new QoiBytesReader(bytes);
    var qHeader = Decoder.DecodeHeader(ref qr);

    //ugly :|
    return qHeader.Channels == Channels.Rgb 
         ? new QImage<RgbPixel>(Decoder.DecodePixels<RgbPixel>(ref qr, in qHeader), qHeader) 
         : new QImage<RgbaPixel>(Decoder.DecodePixels<RgbaPixel>(ref qr, in qHeader), qHeader);
    }

//...
}

public class QImage<T> : QImage where T : unmanaged, IPixel {
    internal QImage(/*args*/) : base(/*params*/) { /*...*/ }

public static QImage<T> New(byte[] pixels, QHeader qHeader) {
    if (typeof(T) == typeof(RgbPixel) || typeof(T) == typeof(RgbaPixel)) 
        return new QImage<T>(pixels, qHeader);
        
    throw new NotSupportedException(
quot;Specified type <{typeof(T).Name}> is not supported. Use <{nameof(RgbPixel)}> or <{nameof(RgbaPixel)}> instead.");
    }
//...
}

internal static unsafe class Decoder {
internal static byte[] DecodePixels<T>(ref QoiBytesReader qr, in QHeader metadata) 
    where T : unmanaged, IPixel { /*decode*/ }

//...
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文