我无法理解接口(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/