英文:
Generic classes with Inheritance
问题
以下是翻译好的内容:
我有下面的方法,它返回一个泛型类的实例。这是一个简单的工厂类。我有一个泛型类叫做FileReader<T>,它可以读取Chase、Products、customers、suppliers等的管道分隔的文本文件,并将数据填充到相应的BusinessObjects中。我试图实现的是一个泛型文件读取器。所有这些业务对象都派生自BusinessBase类。
public override FileReaderGeneric<BusinessBase> CreateFileReader(ImportJobConfig jobConfig)
{
return new FileReaderGeneric<Chase>(jobConfig);
}
BusinessBase不是一个泛型类。BusinessBase只有验证函数。然而,上面的代码给我一个错误
无法隐式将类型<BusinessLayer.Chase>转换为<BusinessLayer.BusinessBase>
根据评论进行了编辑
看起来我的泛型理解不正确
英文:
I am having the below method that returns an instance of a Generic Class. This is a simple factory class. I have a Generic class called FileReader<T> which reads pipe-delimited txt file of Chase,Products, customers, suppliers etc and populate the data into respective BusinessObjects. I am trying to achieve is a Generic file reader. All these business objects derive from BusinessBase class.
public override FileReaderGeneric<BusinessBase> CreateFileReader(ImportJobConfig jobConfig)
{
return new FileReaderGeneric<Chase>(jobConfig);
}
The BusinessBase is not a generic class. The BusinessBase only has validation functions. However, the above code is giving me an error
Cannot implicitly convert type <BusinessLayer.Chase> to <BusinessLayer.BusinessBase>
Edited based on the comments
Looks like my understanding on Generics is not correct
答案1
得分: 1
With C# generics, you cannot cast an instance of a generic class to another. For instance:
class A {
}
class B : A {
}
class Foo<T> where T : A {
}
Foo<A> fooA = new Foo<A>();
Foo<B> fooB = new Foo<B>();
Even though A is the supertype of B, you cannot then say:
fooA = (Foo<A>)fooB;
The language does not allow it: the types Foo<A>
and Foo<B>
are completely unrelated; only their generic parameters are related.
This code:
using System;
class A
{
}
class B : A
{
}
class Foo<T>
where T : A
{
}
public class Program
{
public static void Main()
{
Foo<A> fooA = new Foo<A>();
Foo<B> fooB = new Foo<B>();
Foo<A> xxxx = (Foo<A>)fooB;
}
}
will give you a compilation error Compilation error (line 22, col 17): Cannot convert type 'Foo<B>' to 'Foo<A>'
on the assignment statement:
Foo<A> xxxx = (Foo<A>)fooB;
Updating this to offer possible solutions
Since it sounds like the BusinessBase
instance that you are instantiating are not exposed to the consumers of the instantiated instances of FileReaderGeneric<T>
, there are a couple of things you can do.
Assuming that your generic class looks something like this:
class FileReaderGeneric<T> where T : BusinessBase
{
// ...
}
you can . . .
Use Dependency Injection
class FileReader
{
private BusinessBase bb
private FileReader(BusinessBase bb, ImportJobConfig jobConfig)
{
this.bb = bb;
}
public static FileReader CreateFileReader(BusinessBase bb, ImportJobConfig jobConfig)
{
return new FileReader(bb, jobConfig);
}
}
Use An Abstract Base Class
public abstract class AbstractFileReader
{
// ...
}
class FileReader<T> : AbstractFileReader where T : BusinessBase
{
private FileReader(ImportJobConfig jobConfig)
{
}
public static AbstractFileReader CreateFileReader(ImportJobConfig jobConfig)
{
return new FileReader<Chase>(jobConfig);
}
}
英文:
With C# generics, you cannot cast an instance of a generic class to another. For instance, given
class A {
}
class B : A {
}
class Foo<T> where T:A {
}
Foo<A> fooA = new Foo<A>();
Foo<B> fooB = new Foo<B>();
Even though A is the supertype of B, you cannot then say
fooA = (Foo<A>)fooB;
Even though A
is the supertype of B
. The language does not allow it: the types Foo<A>
and Foo<B>
are completely unrelated: only their generic parameters are related.
This code:
using System;
class A
{
}
class B : A
{
}
class Foo<T>
where T : A
{
}
public class Program
{
public static void Main()
{
Foo<A> fooA = new Foo<A>();
Foo<B> fooB = new Foo<B>();
Foo<A> xxxx = (Foo<A>)fooB;
}
}
will give you a compilation error Compilation error (line 22, col 17): Cannot convert type 'Foo<B>' to 'Foo<A>'
on the assignment statement
Foo<A> xxxx = (Foo<A>)fooB;
Updating this to offer possible solutions
Since it sounds like the BusinessBase
instance that you are instantiating are not exposed to the consumers of the instantiated instances of FileReaderGeneric<T>
, there are a couple of things you can do.
Assuming that your generic class looks something like this:
class FileReaderGeneric<T> where T:BusinessBase
{
...
}
you can . . .
Use Dependency Injection
class FileReader
{
private BusinessBase bb
private FileReader( BusinessBase bb, ImportJobConfig jobConfig )
{
this.bb = bb;
}
public static FileReader CreateFileReader( BusinessBase bb , ImportJobConfig jobConfig )
{
return new FileReader( bb , jobConfig );
}
}
Use An Abstract Base Class
public abstract class AbstractFileReader
{
. . .
}
class FileReader<T> : AbstractFileReader where T:BusinessBase
{
private FileReader( ImportJobConfig jobConfig )
{
}
public static AbstractFileReader CreateFileReader( ImportJobConfig jobConfig )
{
return new FileReader<Chase>( jobConfig );
}
}
答案2
得分: 0
以下是翻译好的代码部分:
你可能想在这里使用一个通用方法。通过类型约束,你可以限制调用者只能使用从BusinessBase派生的类型。像这样:
public override FileReaderGeneric<TBusinessBase> CreateFileReader(ImportJobConfig jobConfig) where TBusinessBase: BusinessBase
{
return new FileReaderGeneric<TBusinessBase>(jobConfig);
}
你需要相应地更改包含此覆盖方法的类,因为这个覆盖方法的签名已经不再与以前相同。
英文:
You likely want to use a generic method here. With type constraints, you can limit callers to using a type derived from BusinessBase. Something like this
public override FileReaderGeneric<TBusinessBase> CreateFileReader(ImportJobConfig jobConfig) where TBusinessBase: BusinessBase
{
return new FileReaderGeneric<TBusinessBase>(jobConfig);
}
You will need to change the containing class appropriately because this overriding method no longer has the same signature it did before.
答案3
得分: 0
public class ImportJobConfig { }
public class BusinessBase { }
public class Chase : BusinessBase { }
public interface IFileReader
public class FileReaderGeneric
public FileReaderGeneric(ImportJobConfig jc) { }
}
public override IFileReader
return (IFileReader
}
英文:
If you create an interface to describe a file reader, and use that interface with a covariant generic type, you can cast the types:
public class ImportJobConfig { }
public class BusinessBase { }
public class Chase : BusinessBase { }
public interface IFileReader<in T> { }
public class FileReaderGeneric<T> : IFileReader<T> {
public FileReaderGeneric(ImportJobConfig jc) { }
}
public override IFileReader<BusinessBase> CreateFileReader(ImportJobConfig jobConfig) {
return (IFileReader<BusinessBase>)(new FileReaderGeneric<Chase>(jobConfig));
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论