C#在泛型对象实例化后更改它
本文关键字:实例化 泛型 对象 | 更新日期: 2023-09-27 18:27:01
SomeClass实例化后,是否可以将TEntity更改为NewEntity?
例如,以这个类定义为例:
public class SomeClass<TEntity> where TEntity : class
{
public void ChangeSet<NewEntity>()
{
TEntity = NewEntity;//not valid
}
}
例如:
var sc = new SomeClass<SomeEntity>();
我怎样才能做到这一点?
sc.ChangeSet<NewEntity>();
在实例化SomeClass之后,是否可以将TEntity更改为NewEntity?
否,这是不可能的。CLR如何知道如何将值从TEntity
映射到SomeEntity
?它们是不同的类型。这就像让你的杂货商把一个苹果变成一个橙子。
不建议使用下面的代码。你需要担心的问题太多了,而且很容易出现错误。我提供它作为你要求CLR做什么的例子。
SomeClass<Foo> fooClass = new SomeClass<Foo>():
//do stuff to fooClass
SomeClass<Baz> = fooClass.ChangeSet<Baz>();
public class SomeClass<T> where T : class
{
public SomeClass<K> ChangeSet<K>() where K:class
{
var changed = new SomeClass<K>();
//manually map the properties over
//but how do you know that Foo.PropertyA fits into Baz.PropetyZed?
//what happens if Foo.A has a string length of 100, but Baz.A has a max length of 50? What do you do?
//What id Foo.ID is an INT and Baz.ID is a GUID?
return changed;
}
}
泛型用于在编译时强制类型安全。最好将new SomeClass<SomeEntity>()
看作一个实际的类本身。事实上,它是作为一个类编译的。基于以下泛型类中静态字段的示例,您可以看到:
public class GenericTest<T> where T : class
{
public static int StaticIntField { get; set; }
public GenericTest(int setGenericIntField)
{
StaticIntField = setGenericIntField;
}
}
用这个测试:
var stringTest =new GenericTest<string>(1);
var objectTest = new GenericTest<object>(2);
System.Diagnostics.Debug.Print(GenericTest<string>.StaticIntField.ToString()); //<-- prints 1
System.Diagnostics.Debug.Print(GenericTest<object>.StaticIntField.ToString()); //<-- prints 2
System.Diagnostics.Debug.Print(GenericTest<Control>.StaticIntField.ToString()); //<-- prints 0 because we haven't created an instance of this type yet
您是否试图将一组TEntity对象转换为一组NewEntity对象?如果是这样的话,那是可能的,但你还没有找到正确的语法
是的,这是我追求的大部分。你能详细说明一下吗?
假设您有一个泛型类C<T>
,它表示一组T
实例,并且您希望将其转换为泛型类C<U>
的实例;一组CCD_ 7实例。您不能更改C<T>
实例的类型,但可以创建一个类型为C<U>
的新对象。签名为:
public class C<T>
{
public C<U> Convert<U>()
{
C<U> result = new C<U>();
// populate the result somehow
return result;
}
}
为了提供实现,进一步假设将一组T
实例转换为一组U
实例的机制是将每个T
转换为U
。您可以提供Func<T, U>
来实现转换。我们还将为C<T>
提供一个构造函数,该构造函数使用IEnumerable<T>
来填充集合:
public class C<T>
{
IEnumerable<T> _items;
public C(IEnumerable<T> items)
{
_items = items;
}
public C<U> Convert<U>(Func<T, U> convertElement)
{
return new C<U>(_items.Select(convertElement));
}
}
我们可以按原样使用它,尽管在这一点上,我们所做的只是在linq到对象之间放置一个笨拙的包装器:
void DoSomething()
{
var integersOneToTen = Enumerable.Range(1, 10);
var myClassOfIntegers = new C<int>(integersOneToTen);
Func<int, string> converter = i => i.ToString();
var myClassOfStrings = myClassOfIntegers.Convert<string>(converter); // the compiler can infer the type argument, but I've included it to reduce ambiguity.
}
其中一些可能与您的需求不兼容;如果是这样的话,请发表评论,我会尽力做出相应的调整。
泛型参数是该类的编译时模板。因此,当您将SomeClass<TEntity>
实例化为SomeClass<int>
时,您或多或少地告诉编译器您有一个类型是"Some Class as applied to int"。
现在,在运行时,您希望能够将"应用于int的SomeClass"重新定义为"应用于{anything}的SomeClass"。但是,"as applied to part"需要在编译时指定,所以不能这样做。
另一种思考方式是想象一下,如果这是普遍实施的。例如,想象一下int上的ChangeSet<T>
方法,其中有人可能会突然将您的int变成字符串、对象或Foo。请注意,不要强制转换它们,而是在运行时更改int的类定义。诶呀