C# 是否有可能以某种方式克服在接口中使用泛型的限制?(无装箱/拆箱)

C# 是否有可能以某种方式克服在接口中使用泛型的限制?(无装箱/拆箱),c#,C#,我正在尝试创建一组将在几个类中使用的接口。但我在正确设置它们时遇到了麻烦。我想保持通用性 我尝试使用动态类型和对象类型来解决这个问题,但没有成功。下面附加的这些接口可能会清楚地说明这一点: 在下面的代码中,类型T未知。我无法指定它,因为每个IDeviceParameter都将是不同的类型。而且参数的数量不是固定的,所以我只想将所有可用的IParameters添加到列表中。我想到的唯一解决方案是使用某种装箱/拆箱(例如将int转换为object,反之亦然)或使用dynamic。或者完全改变这些接口

我正在尝试创建一组将在几个类中使用的接口。但我在正确设置它们时遇到了麻烦。我想保持通用性

我尝试使用动态类型和对象类型来解决这个问题,但没有成功。下面附加的这些接口可能会清楚地说明这一点:

在下面的代码中,类型T未知。我无法指定它,因为每个IDeviceParameter都将是不同的类型。而且参数的数量不是固定的,所以我只想将所有可用的IParameters添加到列表中。我想到的唯一解决方案是使用某种装箱/拆箱(例如将int转换为object,反之亦然)或使用dynamic。或者完全改变这些接口。提前感谢您的建议

public interface IDevice : IDisposable
{
    string Name { get; }
    bool Close();
    Guid DeviceGuid { get; }
    IList<IDeviceParameter<T>>AvailableParameters { get; }
    IList<IDeviceCommand> AvailableCommands { get; }
}



public interface IDeviceParameter<T>
{
    event EventHandler<IDeviceParameter<T>> ParameterValueChanged;
    event EventHandler<Exception> ParameterNotSet;
    string ParameterName { get; }
    string ParameterValue { get; }
    string ParameterUnit { get; }
    bool IsReadOnly { get; }
    T Parameter { get; }
    void SetParameter(T value);
}
公共接口设备:IDisposable
{
字符串名称{get;}
bool-Close();
Guid设备Guid{get;}
IListAvailableParameters{get;}
IList可用命令{get;}
}
公共接口IDeviceParameter
{
事件处理程序参数值已更改;
事件处理程序参数NotSet;
字符串参数名称{get;}
字符串参数值{get;}
字符串参数单位{get;}
bool是只读的{get;}
T参数{get;}
void设置参数(T值);
}
下面是一些具体的实现(由于“无法从类型对象转换为类型int”之类的错误而无法工作):

公共类设备:IDevice
{
公共int_setableParameter1=1;
公共字符串_setableParameter2=“2”;
私有Guid _Guid;
私有字符串\u名称;
私有列表_cmdList=新列表();
私有列表_paramList=新列表();
公共设备()
{
IDeviceParameter setableParameter1=DeviceParameterFactory.Factory.CreateParameter(“SomeParameter1”,“V”,委托{抛出新的DeviceParameterFactory.ParametersNotSetException(“SomeParameter1”);},引用_setableParameter1);
IDeviceParameter setableParameter2=DeviceParameterFactory.Factory.CreateParameter(“SomeParameter2”,“V”,委托{抛出新的DeviceParameterFactory.ParametersNotSetException(“SomeParameter2”);},引用_setableParameter2);
_添加(setableParameter1);
_添加(setableParameter2);
_guid=guid.NewGuid();
_name=“Device”+DateTime.Now.毫秒;
}

一些解释:factory类返回IDeviceParameter,这些类型在编译时肯定是已知的,因为它们是明确设置的。

如果您有
IDeviceParameter
类型的东西和
IDeviceParameter
类型的东西,那么在不执行的情况下就无法将其转换为
IDeviceParameter
ode>new IDeviceParameter()。这是因为它们只是程序的完全不同的接口。对于编译器,您最好创建名为
IIntDeviceParameter
IStringDeviceParameter
的类

如果这些类共享一个类似的接口,那么您需要显式地说明这一点,即您需要创建一个接口
IUnknownTypeDeviceParameter
,但您不能将在其类型定义中使用T的字段或方法放在其中。因此您可以这样做:

公共接口IUnknownTypeDeviceParameter
{
事件处理程序参数NotSet;
字符串参数名称{get;}
字符串参数值{get;}
字符串参数单位{get;}
bool是只读的{get;}
}
公共接口IDeviceParameter:IUnknownTypeDeviceParameter
{
事件处理程序参数值已更改;
事件处理程序参数NotSet;
字符串参数名称{get;}
字符串参数值{get;}
字符串参数单位{get;}
bool是只读的{get;}
T参数{get;}
void设置参数(T值);
}

如果您想在
iUnknownTypedViceParameter
上使用
IDeviceParameter
中的函数之一,您需要将其转换回
IDeviceParameter
如果您有
IDeviceParameter
类型和
IDeviceParameter
类型的函数,则无法将其转换为一个
IDeviceParameter
而不在某个地方执行
new IDeviceParameter()
。这是因为它们只是程序的完全不同的接口。对于编译器,您最好创建名为
IIntDeviceParameter
IStringDeviceParameter
的类

如果这些类共享一个类似的接口,那么您需要显式地说明这一点,即您需要创建一个接口
IUnknownTypeDeviceParameter
,但您不能将在其类型定义中使用T的字段或方法放在其中。因此您可以这样做:

公共接口IUnknownTypeDeviceParameter
{
事件处理程序参数NotSet;
字符串参数名称{get;}
字符串参数值{get;}
字符串参数单位{get;}
bool是只读的{get;}
}
公共接口IDeviceParameter:IUnknownTypeDeviceParameter
{
事件处理程序参数值已更改;
事件处理程序参数NotSet;
字符串参数名称{get;}
字符串参数值{get;}
字符串参数单位{get;}
bool是只读的{get;}
T参数{get;}
void设置参数(T值);
}

如果您想在
IUnknownTypeDeviceParameter
上使用
IDeviceParameter
中的函数之一,您需要将其转换回
IDeviceParameter

您将如何使用这些
可用参数
?让我们想象一下,您已经找到了一种方法来实现这一点(例如,使用
dynamic
),您收到了某种类型的
IDeviceParameter
。当您在编译时不知道类型时,您将如何处理此问题?如果在编译时无法知道
T
,请不要这样做
public class Device : IDevice
{
    public int _setableParameter1 = 1;
    public string _setableParameter2 = "2";
    private Guid _guid;
    private string _name;
    private List<IDeviceCommand> _cmdList = new List<IDeviceCommand>();
    private List<IDeviceParameter<object>> _paramList = new List<IDeviceParameter<object>>();

   public Device()
   {
        IDeviceParameter<int> setableParameter1 = DeviceParameterFactory.Factory<int>.CreateParameter("SomeParameter1", "V", delegate { throw new DeviceParameterFactory.ParametersNotSetException("SomeParameter1"); },  ref _setableParameter1);
         IDeviceParameter<string> setableParameter2 = DeviceParameterFactory.Factory<string>.CreateParameter("SomeParameter2", "V", delegate { throw new DeviceParameterFactory.ParametersNotSetException("SomeParameter2"); },  ref _setableParameter2);
        _cmdList.Add(setableParameter1);
        _cmdList.Add(setableParameter2);
        _guid = Guid.NewGuid();
        _name = "Device" + DateTime.Now.Millisecond;
    }