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