c# - Int32 和 int 的泛型方法区别

标签 c# generics interface

我无法理解接口(interface)中的泛型方法。我正在使用带有自动 C# 版本的 .NET Framework 4.8,因此它应该是 C# 7.3。下面的例子

接口(interface)是:

public interface IRegister
{
  Nullable<T> Read<T>() where T: struct;
  void Write<T>(T value) where T : struct;
}

现在一些类继承接口(interface):

public abstract class AbstractRegister : IRegister
{
  protected ModbusClient client;
  protected int Address;
  public abstract Nullable<T> Read<T>() where T : struct;
  public virtual void Write<T>(T value) where T : struct
  {
    return;
  }
  public AbstractRegister(int address, ModbusClient client)
  {
    this.client = client;
    this.Address = address;
  }
}

现在我有一些从 AbstractRegister 继承的类:

class InputRegister_int : AbstractRegister
{
  public InputRegister_int(int address, ModbusClient client) : base(address, client) { }

  public override int? Read<int>()
  {
    if (client == null)
      return null;
    return this.client.ReadInputRegisters(this.Address, 1)[0] as int?;
  }
}

并排队public override int? Read<int>()我有错误:

CS1001: Identifier expected
CS1003: Syntax error, '>' expected
CS1003: Syntax error, '(' expected

我正在使用 Visual Studio Community 2022

当我使用 Int32 而不是 int 时,一切正常,它几乎解决了我的问题,但类型 float (这对我来说是必需的)没有 Float 表示。

我已经没有办法解决这个问题了。有人可以给我解释一下吗?

最佳答案

也许尝试将接口(interface)更改为泛型,这样泛型类型引用就被限制为相同类型,而不仅仅是任意任何类型:

public interface IRegister<T> 
    where T : struct
{
    Nullable<T> Read();
    void Write(T value);
}

public abstract class AbstractRegister<T> : IRegister<T>
    where T : struct
{
    protected ModbusClient client;
    protected int Address;
    public abstract Nullable<T> Read();
    public virtual void Write(T value)
    {
        return;
    }
    public AbstractRegister(int address, ModbusClient client)
    {
        this.client = client;
        this.Address = address;
    }
}

class InputRegister_int : AbstractRegister<int>
{
    public InputRegister_int(int address, ModbusClient client) : base(address, client) { }

    public override int? Read()
    {
        if (client == null)
          return null;
          return this.client.ReadInputRegisters(this.Address, 1)[0] as int?;
    }
}

class InputRegister_float : AbstractRegister<float>
{
    public InputRegister_float(int address, ModbusClient client) : base(address, client) { }

    public override float? Read()
    {
        if (client == null)
          return null;
          return this.client.ReadInputRegisters(this.Address, 1)[0] as float?;
    }
}

此处的功能差异在于,在类级别指定通用类型,基类中的所有 T 必须相同,因此对于 InputRegister_int 所有 T现在是 int

从语法角度来看,请注意这些方法的原型(prototype)上没有后缀,这是因为它们根本不是泛型方法,它们专门输入到与之前相同的类型参数创建实例时指定。

如果您确实有这样的方法:

Nullable<T> Read<T>() where T: struct;

然后,即使对于 InputRegister_int 类,我们也可以将 ANY 类型的结构传递给该方法并期望它返回值,以下内容预计是有效的在运行时:

var intRegister = new InputRegister_int();
int intValue = intRegister.Read<int>();
DateTime dtValue = intRegister.Read<DateTime>();

如果您确实希望寄存器是任何任意类型,那么我们根本不需要抽象寄存器:

public class GenericRegister : IRegister
{
    protected ModbusClient client;
    protected int Address;
    public virtual Nullable<T> Read<T>() where T : struct
    {
        if (client == null)
            return null;
            return this.client.ReadInputRegisters(this.Address, 1)[0] as T?;        
    }
    public virtual void Write<T>(T value) where T : struct
    {
        // TODO: implement generic write logic
        return;
    }
    public AbstractRegister(int address, ModbusClient client)
    {
        this.client = client;
        this.Address = address;
    }
}

然而,这会导致非常懒惰的实现,ModBus 寄存器中的值类型不会改变,大多数固定为硬件实现,但 PLC 中的内部逻辑将为您限制类型。您的固定类型 InputRegister_int 允许您在需要时对客户端的响应进行特定值和类型检查,并有助于指导开发人员稍后做出合理的决策。

关于c# - Int32 和 int 的泛型方法区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71118358/

相关文章:

c# - 裁剪图像时出现 OutofMemory 错误

c# - Xamarin.IOS MonoTouch.Dialog ExpandableDatePickerElement 无法正常工作

c# - 对泛型类型的构造函数约束或只是检查我的泛型类型构造函数中的约束?

C# generics - 我可以让 T 成为两个选择之一吗?

ios - Swift:如何从函数返回类类型

c++ - STL 容器和二进制接口(interface)兼容性

c# - 制作按钮 Xna/MonoGame

c# - 通过串口从电压表读取数据

interface - Golang : Can I cast to chan interface{}

java - 变形金刚类设计