C# 编译时类型检查
想象一个泛型类BC# 编译时类型检查,c#,generics,collections,parameters,C#,Generics,Collections,Parameters,想象一个泛型类B public class B<T> : IB { public void Foo(object parameter) { var param = (T)parameter; //... } } 稍后,我想在类A上执行一些方法,比如foo,它将获取T类型的对象集合,其中T是构造函数中传递的B实例的泛型。所以这些类型必须匹配 public void foo(IEnumerable<object> param) {
public class B<T> : IB
{
public void Foo(object parameter)
{
var param = (T)parameter;
//...
}
}
稍后,我想在类A上执行一些方法,比如foo,它将获取T
类型的对象集合,其中T
是构造函数中传递的B
实例的泛型。所以这些类型必须匹配
public void foo(IEnumerable<object> param)
{
for (int i = 0; i < collectionOfBs.Count(); i++)
{
collectionOfBs.ElementAt(i).Foo(param.ElementAt(i));
}
}
public void foo(IEnumerable参数)
{
对于(int i=0;i
现在我正在传递一个IEnumerable
并将其转换为foo内部的T
类型,这将起作用,但我想知道是否可以在编译时进行此类型检查
有没有可能的想法?
谢谢您可以使用提供参数类型的通用方法来尝试此操作 它不能确保TParam和T是相同的,因为您有一个非通用接口,但据我所知,根据对您的问题的第一次研究,这是您所能做到的最好的 因为在C#中没有菱形操作符来允许开放类型上的真正泛型多态性
public interface IB
{
void Foo<TParam>(TParam parameter);
}
public class B<T> : IB
{
public void Foo<TParam>(TParam parameter)
{
var param = parameter;
Console.WriteLine("param type: " + param.GetType().Name);
}
}
public class A
{
private IEnumerable<IB> CollectionOfBs;
public A(IEnumerable<IB> collectionOfBs)
{
CollectionOfBs = collectionOfBs;
}
public void Foo(IEnumerable<object> param)
{
if ( param.Count() < CollectionOfBs.Count() )
throw new ArgumentException();
for ( int i = 0; i < CollectionOfBs.Count(); i++ )
CollectionOfBs.ElementAt(i).Foo(param.ElementAt(i));
}
}
考虑
这里的问题是,任何错误的匹配参数类型都可能被传递
例如,对于Test(),您可以使用一个double而不是第一个整数,它可以工作:在Int32实例上获得一个double
param type: Double
param type: Double
param type: String
使用菱形操作符
您将能够使用通用接口并在封闭的构造类型列表上进行解析。。。您的设计将具有更好的气味:
public interface IB<T>
{
void Foo(T parameter);
}
public class B<T> : IB<T>
{
public void Foo(T parameter)
{
var param = parameter;
Console.WriteLine("param type: " + param.GetType().Name);
}
}
public class A
{
private IEnumerable<IB<>> CollectionOfBs;
public A(IEnumerable<IB<>> collectionOfBs)
{
CollectionOfBs = collectionOfBs;
}
public void Foo(IEnumerable<object> param)
{
if ( param.Count() < CollectionOfBs.Count() )
throw new ArgumentException();
for ( int i = 0; i < CollectionOfBs.Count(); i++ )
{
CollectionOfBs.ElementAt(i).Foo(param.ElementAt(i));
}
}
}
公共接口IB
{
void-Foo(T参数);
}
B级:IB
{
公共void Foo(T参数)
{
var param=参数;
WriteLine(“参数类型:”+param.GetType().Name);
}
}
公共A类
{
私人收藏;
公共A(IEnumerable CollectionFBS)
{
CollectionOfBs=CollectionOfBs;
}
公共void Foo(IEnumerable参数)
{
if(param.Count()
因此,任何错误的匹配类型的参数都会在运行时引发异常。如果需要一致的泛型类型检查,则需要一致地应用泛型。目前,您使用的是一种折衷方法:
B
是通用的,但IB
不是。然后您有一个非泛型类a
,该类耦合到非泛型接口IB
,但您需要对T
进行编译时类型检查,而a
和IB
对此一无所知(只是在内部将其强制转换为T
)。这有点问题
从类/接口的使用情况来看,显然您不希望在A
中使用混合的IB
实现,因此您可以做的是在所有类型上一致地应用泛型类型参数t
:
public class B<T> : IB<T>
{
public void Foo(T parameter)
{
var param = parameter;
//...
}
}
public class A<T>
{
public A(IEnumerable<IB<T>> collectionOfBs) {}
public void foo(IEnumerable<T> param)
{
collectionOfBs.Zip(param, (b, t) => { b.Foo(t); return 0 });
}
}
公共B类:IB
{
公共void Foo(T参数)
{
var param=参数;
//...
}
}
公共A类
{
公共A(IEnumerable collectionOfBs){}
公共void foo(IEnumerable参数)
{
collectionOfBs.Zip(param,(b,t)=>{b.Foo(t);返回0});
}
}
请注意,我将您的方法替换为
for
和ElementAt
byEnumerable.Zip
就您所写的内容所知,IB的具体类可能根本就没有这样的方法可以使用。您还可以使您的IB
接口通用。IB
对类型T
一无所知。只有类B
知道T
是什么。我能想到的一个选择是将方法foo
放在类B
insteadmagine havingvar b1=new B();var b2=新的B()
然后创建一个A
的实例,如下所示vara=newa(newib[]{b1,b2})代码>。在这种情况下,“在构造函数中传递的B实例的泛型类型”是什么?更不用说a=newa(newib[]{b1,b2,c})的情况
和c
是c
类型的对象,它也实现了IB
@AhmedAbdelhameed。可执行项必须看起来像{5,“bar}。这回答了你的问题吗?@SimplyGed我不认为这是一个选项,foo
迭代IB
的所有实例,并将参数传递给它们。但是在这里,A的实例将决定类型t
,因此B
的所有实例也必须具有相同的泛型t
?(见艾哈迈德的评论和我的回答)看起来很有希望,我稍后会检查,现在没有时间;)
param type: Double
param type: Double
param type: String
public interface IB<T>
{
void Foo(T parameter);
}
public class B<T> : IB<T>
{
public void Foo(T parameter)
{
var param = parameter;
Console.WriteLine("param type: " + param.GetType().Name);
}
}
public class A
{
private IEnumerable<IB<>> CollectionOfBs;
public A(IEnumerable<IB<>> collectionOfBs)
{
CollectionOfBs = collectionOfBs;
}
public void Foo(IEnumerable<object> param)
{
if ( param.Count() < CollectionOfBs.Count() )
throw new ArgumentException();
for ( int i = 0; i < CollectionOfBs.Count(); i++ )
{
CollectionOfBs.ElementAt(i).Foo(param.ElementAt(i));
}
}
}
public class B<T> : IB<T>
{
public void Foo(T parameter)
{
var param = parameter;
//...
}
}
public class A<T>
{
public A(IEnumerable<IB<T>> collectionOfBs) {}
public void foo(IEnumerable<T> param)
{
collectionOfBs.Zip(param, (b, t) => { b.Foo(t); return 0 });
}
}