c# 转换泛型接口的非泛型实现
c# casting non generic implement of generic interface
我阅读了很多可能的答案,但没有找到适合我需要的答案!
我正在尝试声明一个通用接口,具有不同的非通用实现 类,然后在同一上下文中使用此 类。
这是我目前所拥有的:
接口
public interface WeirdType { }
public class WeirdType1 : WeirdType { }
public class WeirdType2 : WeirdType { }
public interface IGenericInterface<T>
{
T GiveT();
void TakeItBack(T data);
}
实现
public class NonGenericImplementation1 : IGenericInterface<WeirdType1>
{
public WeirdType1 GiveT() { return new WeirdType1(); }
public void TakeItBack(WeirdType1 data) { Console.WriteLine("Got it back 1"); }
}
public class NonGenericImplementation2 : IGenericInterface<WeirdType2>
{
public WeirdType2 GiveT() { return new WeirdType2(); }
public void TakeItBack(WeirdType2 data) { Console.WriteLine("Got it back 2"); }
}
用法
List<IGenericInterface<WeirdType>> implementations = new List<IGenericInterface<WeirdType>>
{
new NonGenericImplementation1(),
new NonGenericImplementation2()
};
foreach (var impl in implementations)
{
WeirdType x = impl.GiveT();
impl.TakeItBack(x);
}
这让我很生气
'Argument Type NonGenericImplementation1 is not assignable to IGenericInterface<WeirdType>'
即使一些黑魔法让我通过编译,它也会因为同样的原因在运行时崩溃。
帮我理解是什么让 C# 打字变得不可能and/or 建议稍微复杂一些的模式来顺利完成
我可以用很多不同的方法解决我的实际问题,所以完全替代的解决方案并不是我真正想要的
很明显,如果实际答案已经存在,很抱歉浪费时间
一如既往,没有上下文很难做到中肯,但我会尽力提供帮助。
错误 'Argument Type NonGenericImplementation1 is not assignable to IGenericInterface' 在我看来完全没问题,在 C# 中,集合的不同成员必须具有相同的类型。
但是你为什么声明:
public class NonGenericImplementation1 : IGenericInterface<WeirdType1>
public class NonGenericImplementation2 : IGenericInterface<WeirdType2>
而不是:
public class NonGenericImplementation1 : IGenericInterface<WeirdType>
public class NonGenericImplementation2 : IGenericInterface<WeirdType>
这样,您的所有示例代码仍然有效,并且两者 类 将实现相同的接口,因此您现在可以声明:
List<IGenericInterface<WeirdType>> implementations = new List<IGenericInterface<WeirdType>>
{
new NonGenericImplementation1(),
new NonGenericImplementation2()
};
希望对您有所帮助。
IGenericInterface<WeirdType1>
不是 IGenericInterface<WeirdType>
,即使 WeirdType1
实现了 WeirdType
。
问题是,如果你从 implementations
中取出一些东西,我们知道它的类型是 IGenericInterface<WeirdType>
。这意味着我们应该能够调用 GiveT
并获得 WeirdType
和 TakeItBack
,同时将其传递给 WeirdType
.
特别是这意味着以下两项必须有效:
impl.TakeItBack(new WeirdType1());
impl.TakeItBack(new WeirdType2());
现在,如果 impl
是 NonGenericImplementation1
类型,则第二个无效,如果它是 NonGenericImplementation2
类型,则第一个无效。
这意味着我们不能声称 NonGenericImplementation1
是 IGenericInterface<WeirdType>
类型并且 NonGenericImplementation2
也是如此。
您没有任何实现 IGenericInterface 的非泛型 class。
您的 "implements" 集合只能接受实现上述接口的类型的对象。
这就是泛型的美妙之处。它们是强类型的,特别是当你处理泛型的泛型时,它变得更具挑战性。但是没有办法。
首先,Generic List 将不接受任何未实现 IGenericInterface 类型的对象。接下来,当您拥有那种 class 时,即使该类型是从 "WeirdType".[=12= 继承的,它也将不允许使用 "WeirdType" 以外的类型实例化的对象]
所以泛型中的继承在第一层有帮助,但除此之外就没有帮助了。
您的问题有解决方案。它不是 100% 有效的解决方案,许多 OOP 专家不会同意这一点,但它具有您想要的 class 结构并且可以按照您想要的方式工作。
您需要创建子 class 如下。
public class GenericClass<T> : IGenericInterface<T> where T : WeirdType
{
public virtual T GiveT()
{
return default(T);
}
public virtual void TakeItBack(T data)
{
}
}
public class NonGenericClass1 : GenericClass<WeirdType1>, IGenericInterface<WeirdType>
{
public override WeirdType1 GiveT()
{
return new WeirdType1();
}
public void TakeItBack(WeirdType data)
{
Console.WriteLine("Got it back 1");
}
public override void TakeItBack(WeirdType1 data)
{
this.TakeItBack(data);
}
WeirdType IGenericInterface<WeirdType>.GiveT()
{
return GiveT();
}
}
public class NonGenericClass2 : GenericClass<WeirdType2>, IGenericInterface<WeirdType>
{
public WeirdType2 GiveT()
{
return new WeirdType2();
}
public void TakeItBack(WeirdType data)
{
Console.WriteLine("Got it back 2");
}
public override void TakeItBack(WeirdType2 data)
{
this.TakeItBack(data);
}
WeirdType IGenericInterface<WeirdType>.GiveT()
{
return this.GiveT();
}
}
现在您可以初始化通用接口的集合,并将子 classes 的对象添加到其中。
var obj1 = new NonGenericClass1();
var obj2 = new NonGenericClass2();
List<IGenericInterface<WeirdType>> implementations = new List<IGenericInterface<WeirdType>>
{
obj1, obj2
};
foreach (var impl in implementations)
{
WeirdType x = impl.GiveT();
impl.TakeItBack(x);
}
这应该可以解决您的问题。
感谢大家的意见,我尽量不重复与 T 无关的代码,样板文件越少越好。
我采用的解决方案是添加抽象 class 实现额外的接口。
这并不令我满意,因为我相信您应该能够为泛型编写类型不可知的代码,因此无需修改实际的 classes 和接口 code/hierarchy 也不会滥用反射。
这可以通过扩展方法和 non-typed 泛型列表实现,后者在 C# 中不受支持。
这是额外的代码:
public interface IComplexable { void DoComplexStuff(); }
public abstract class GenericImplementation<T> : IGenericInterface<T>, IComplexable
{
public abstract T GiveT();
public abstract void TakeItBack(T data);
public void DoComplexStuff()
{
T x = GiveT();
TakeItBack(x);
}
}
类 声明:
public class NonGenericImplementation1 : GenericImplementation<WeirdType1>
public class NonGenericImplementation2 : GenericImplementation<WeirdType2>
用法:
var impl = new IComplexable[] { new NonGenericImplementation1(),new NonGenericImplementation2() };
foreach (var complexable in impl)
{
complexable.DoComplexStuff();
}
我阅读了很多可能的答案,但没有找到适合我需要的答案!
我正在尝试声明一个通用接口,具有不同的非通用实现 类,然后在同一上下文中使用此 类。
这是我目前所拥有的:
接口
public interface WeirdType { }
public class WeirdType1 : WeirdType { }
public class WeirdType2 : WeirdType { }
public interface IGenericInterface<T>
{
T GiveT();
void TakeItBack(T data);
}
实现
public class NonGenericImplementation1 : IGenericInterface<WeirdType1>
{
public WeirdType1 GiveT() { return new WeirdType1(); }
public void TakeItBack(WeirdType1 data) { Console.WriteLine("Got it back 1"); }
}
public class NonGenericImplementation2 : IGenericInterface<WeirdType2>
{
public WeirdType2 GiveT() { return new WeirdType2(); }
public void TakeItBack(WeirdType2 data) { Console.WriteLine("Got it back 2"); }
}
用法
List<IGenericInterface<WeirdType>> implementations = new List<IGenericInterface<WeirdType>>
{
new NonGenericImplementation1(),
new NonGenericImplementation2()
};
foreach (var impl in implementations)
{
WeirdType x = impl.GiveT();
impl.TakeItBack(x);
}
这让我很生气
'Argument Type NonGenericImplementation1 is not assignable to IGenericInterface<WeirdType>'
即使一些黑魔法让我通过编译,它也会因为同样的原因在运行时崩溃。
帮我理解是什么让 C# 打字变得不可能and/or 建议稍微复杂一些的模式来顺利完成
我可以用很多不同的方法解决我的实际问题,所以完全替代的解决方案并不是我真正想要的
很明显,如果实际答案已经存在,很抱歉浪费时间
一如既往,没有上下文很难做到中肯,但我会尽力提供帮助。
错误 'Argument Type NonGenericImplementation1 is not assignable to IGenericInterface' 在我看来完全没问题,在 C# 中,集合的不同成员必须具有相同的类型。
但是你为什么声明:
public class NonGenericImplementation1 : IGenericInterface<WeirdType1>
public class NonGenericImplementation2 : IGenericInterface<WeirdType2>
而不是:
public class NonGenericImplementation1 : IGenericInterface<WeirdType>
public class NonGenericImplementation2 : IGenericInterface<WeirdType>
这样,您的所有示例代码仍然有效,并且两者 类 将实现相同的接口,因此您现在可以声明:
List<IGenericInterface<WeirdType>> implementations = new List<IGenericInterface<WeirdType>>
{
new NonGenericImplementation1(),
new NonGenericImplementation2()
};
希望对您有所帮助。
IGenericInterface<WeirdType1>
不是 IGenericInterface<WeirdType>
,即使 WeirdType1
实现了 WeirdType
。
问题是,如果你从 implementations
中取出一些东西,我们知道它的类型是 IGenericInterface<WeirdType>
。这意味着我们应该能够调用 GiveT
并获得 WeirdType
和 TakeItBack
,同时将其传递给 WeirdType
.
特别是这意味着以下两项必须有效:
impl.TakeItBack(new WeirdType1());
impl.TakeItBack(new WeirdType2());
现在,如果 impl
是 NonGenericImplementation1
类型,则第二个无效,如果它是 NonGenericImplementation2
类型,则第一个无效。
这意味着我们不能声称 NonGenericImplementation1
是 IGenericInterface<WeirdType>
类型并且 NonGenericImplementation2
也是如此。
您没有任何实现 IGenericInterface 的非泛型 class。
您的 "implements" 集合只能接受实现上述接口的类型的对象。
这就是泛型的美妙之处。它们是强类型的,特别是当你处理泛型的泛型时,它变得更具挑战性。但是没有办法。
首先,Generic List 将不接受任何未实现 IGenericInterface 类型的对象。接下来,当您拥有那种 class 时,即使该类型是从 "WeirdType".[=12= 继承的,它也将不允许使用 "WeirdType" 以外的类型实例化的对象]
所以泛型中的继承在第一层有帮助,但除此之外就没有帮助了。
您的问题有解决方案。它不是 100% 有效的解决方案,许多 OOP 专家不会同意这一点,但它具有您想要的 class 结构并且可以按照您想要的方式工作。
您需要创建子 class 如下。
public class GenericClass<T> : IGenericInterface<T> where T : WeirdType
{
public virtual T GiveT()
{
return default(T);
}
public virtual void TakeItBack(T data)
{
}
}
public class NonGenericClass1 : GenericClass<WeirdType1>, IGenericInterface<WeirdType>
{
public override WeirdType1 GiveT()
{
return new WeirdType1();
}
public void TakeItBack(WeirdType data)
{
Console.WriteLine("Got it back 1");
}
public override void TakeItBack(WeirdType1 data)
{
this.TakeItBack(data);
}
WeirdType IGenericInterface<WeirdType>.GiveT()
{
return GiveT();
}
}
public class NonGenericClass2 : GenericClass<WeirdType2>, IGenericInterface<WeirdType>
{
public WeirdType2 GiveT()
{
return new WeirdType2();
}
public void TakeItBack(WeirdType data)
{
Console.WriteLine("Got it back 2");
}
public override void TakeItBack(WeirdType2 data)
{
this.TakeItBack(data);
}
WeirdType IGenericInterface<WeirdType>.GiveT()
{
return this.GiveT();
}
}
现在您可以初始化通用接口的集合,并将子 classes 的对象添加到其中。
var obj1 = new NonGenericClass1();
var obj2 = new NonGenericClass2();
List<IGenericInterface<WeirdType>> implementations = new List<IGenericInterface<WeirdType>>
{
obj1, obj2
};
foreach (var impl in implementations)
{
WeirdType x = impl.GiveT();
impl.TakeItBack(x);
}
这应该可以解决您的问题。
感谢大家的意见,我尽量不重复与 T 无关的代码,样板文件越少越好。
我采用的解决方案是添加抽象 class 实现额外的接口。
这并不令我满意,因为我相信您应该能够为泛型编写类型不可知的代码,因此无需修改实际的 classes 和接口 code/hierarchy 也不会滥用反射。
这可以通过扩展方法和 non-typed 泛型列表实现,后者在 C# 中不受支持。
这是额外的代码:
public interface IComplexable { void DoComplexStuff(); }
public abstract class GenericImplementation<T> : IGenericInterface<T>, IComplexable
{
public abstract T GiveT();
public abstract void TakeItBack(T data);
public void DoComplexStuff()
{
T x = GiveT();
TakeItBack(x);
}
}
类 声明:
public class NonGenericImplementation1 : GenericImplementation<WeirdType1>
public class NonGenericImplementation2 : GenericImplementation<WeirdType2>
用法:
var impl = new IComplexable[] { new NonGenericImplementation1(),new NonGenericImplementation2() };
foreach (var complexable in impl)
{
complexable.DoComplexStuff();
}