C# 避免使用泛型和自定义数据列表强制转换
我有以下代码来支持不同类型的列表:C# 避免使用泛型和自定义数据列表强制转换,c#,.net,generics,interface,C#,.net,Generics,Interface,我有以下代码来支持不同类型的列表: public enum eType { tInt, tString, tDateTime } public interface ICustomType<out T> { T Value { get; } } public abstract class DifferentType { protected DifferentType(eType type, string mnemonic) {
public enum eType
{
tInt,
tString,
tDateTime
}
public interface ICustomType<out T>
{
T Value { get; }
}
public abstract class DifferentType
{
protected DifferentType(eType type, string mnemonic)
{
Type = type;
Mnemonic = mnemonic;
}
public string Mnemonic { get; private set; }
public eType Type { get; private set; }
}
public class DateTimeType : DifferentType, ICustomType<DateTime>
{
public DateTimeType(DateTime value, string mnemonic)
: base(eType.tDateTime, mnemonic)
{
Value = value;
}
public DateTime Value { get; private set; }
}
public class IntType : DifferentType, ICustomType<int>
{
public IntType(int value, string mnemonic)
: base(eType.tInt, mnemonic)
{
Value = value;
}
public int Value { get; private set; }
}
public class StringType : DifferentType, ICustomType<string>
{
public StringType(string value, string mnemonic)
: base(eType.tString, mnemonic)
{
Value = value;
}
public string Value { get; private set; }
}
public static class UtilValue
{
public static T GetValue<T>(DifferentType customType)
{
return ((ICustomType<T>)customType).Value;
}
}
public class testTypes2
{
public testTypes2()
{
var values = new List<DifferentType> { GetInt(), GetString(), GetDate() };
foreach (var i in values)
{
switch (i.Type)
{
case eType.tInt:
int resInt = UtilValue.GetValue<int>(i);
break;
case eType.tString:
string resString = UtilValue.GetValue<string>(i);
break;
case eType.tDateTime:
DateTime resDateTime = UtilValue.GetValue<DateTime>(i);
break;
}
}
}
private DateTimeType GetDate()
{
return new DateTimeType(new DateTime(2000, 1, 1), "MnemonicDate");
}
private IntType GetInt()
{
return new IntType(5, "MnemonicInt");
}
private StringType GetString()
{
return new StringType("ok", "MnemonicString");
}
}
公共枚举eType
{
色调,
tString,
tDateTime
}
公共接口ICustomType
{
T值{get;}
}
公共抽象类不同类型
{
受保护的差异类型(eType类型,字符串助记符)
{
类型=类型;
助记符=助记符;
}
公共字符串助记符{get;private set;}
公共eType类型{get;private set;}
}
公共类DateTimeType:DifferentitType,ICustomType
{
公共日期时间类型(日期时间值,字符串助记符)
:base(eType.tDateTime,助记符)
{
价值=价值;
}
公共日期时间值{get;private set;}
}
公共类IntType:DifferentitType,ICustomType
{
公共IntType(int值,字符串助记符)
:base(eType.tInt,助记符)
{
价值=价值;
}
公共int值{get;private set;}
}
公共类StringType:DifferentitType,ICustomType
{
公共StringType(字符串值、字符串助记符)
:base(eType.tString,助记符)
{
价值=价值;
}
公共字符串值{get;private set;}
}
公共静态类UtilValue
{
公共静态T GetValue(不同类型customType)
{
返回((ICustomType)customType).Value;
}
}
公共类testTypes2
{
公共测试类型2()
{
var values=新列表{GetInt(),GetString(),GetDate()};
foreach(值中的var i)
{
开关(i型)
{
大小写eType.tInt:
int resInt=UtilValue.GetValue(i);
打破
case eType.t字符串:
字符串resString=UtilValue.GetValue(i);
打破
case eType.tDateTime:
DateTime resDateTime=UtilValue.GetValue(i);
打破
}
}
}
私有日期时间类型GetDate()
{
返回新的DateTimeType(新的DateTime(2000,1,1),“助记符”);
}
私有IntType GetInt()
{
返回新的IntType(5,“助记符”);
}
私有StringType GetString()
{
返回新的StringType(“ok”、“助记符”);
}
}
并希望避免在return((ICustomType)customType.Value行强制转换
在UtilValue
类中,你知道我如何在保留设计的同时摆脱它吗
我甚至不确定这个演员的表演是否昂贵?我的猜测是肯定的。访客模式示例:
interface IDifferentTypeVisitor
{
void Visit(DateTimeType dt);
void Visit(StringType st);
}
class DifferentType
{
public abstract void Accept(IDifferentTypeVisitor visitor);
}
class DateTimeType : DifferentType
{
public void Accept(IDifferentTypeVisitor visitor)
{
visitor.Visit(this);
}
}
class StringType : DifferentType
{
public void Accept(IDifferentTypeVisitor visitor)
{
visitor.Visit(this);
}
}
class SomeVisitor : IDifferentTypeVisitor
{
public void Visit(DateTimeType dt)
{
//DateTime resDateTime = dt.Value; Or similar
}
public void Visit(StringType st)
{
//string resString = st.Value; Or similar
}
}
public class testTypes2
{
public testTypes2()
{
var values = new List<DifferentType> { /* Content */ };
var visitor = new SomeVisitor();
foreach (var i in values)
{
i.Accept(visitor);
}
}
}
然后删除所有其他
Accept
方法。这会影响性能,但看起来更好;-) 你应该进入访客模式:这应该可以解决你的问题,避免演员和开关。@LasseSpeholt:Hi!这看起来是一个有趣的想法,但不确定如何正确实施。我将不得不读几遍这篇文章,并玩弄这个想法……谢谢你的建议。如果你能给出这个想法的答案,那就太棒了!现在有一个例子。确切的代码取决于您想在交换机中执行的操作。感谢您提供答案!这很有趣,但是我发现它有点太拘束了,或者可能是我没有正确理解这个概念。我只能在访问者中操作自定义数据类型(例如,DateTimeType
),如何在测试类(在循环中)中公开和使用它?@ibiza您想在循环中做什么?请记住,您可以随时向访问者添加状态。我正在考虑直接在循环中操作数据(出于我的目的,我修改了您的答案,每个自定义数据都有一个与其类型相对应的值属性,例如公共日期时间值{get;private set;}
,用于日期时间类型
)。例如,我可以在测试类中有一个列表
,并希望将日期时间类型
的所有值添加到该列表中。@ibiza然后您只需将该列表存储在SomeVisitor
中,并在访问(数据时间类型)
中将日期时间添加到该列表中。在testTypes2
中,使用方法或属性从访问者检索列表。
public void Accept(IDifferentTypeVisitor visitor)
{
visitor.Visit((dynamic)this);
}