Iri*_*son 14 c# generics class
我们最近了解了C#中的泛型类,但我们的老师没有提到它们可以用于什么.我真的找不到任何好的例子,如果有人帮助我,我会非常高兴:)
你有自己的通用课程吗?你用它做了什么?
一些代码示例会让我和我的同学们真的很开心!请原谅,英语不好,我来自瑞典:)
快乐的编程!
对不起 - 我想我可以把问题写得好一点.我熟悉通用集合.我只是想知道你自己的泛型类可以用于什么.
并且感谢您的MSDN链接,我在发布问题之前就已经阅读了它们,但也许我错过了什么?我会再看看!
Cha*_*lie 10
通用集合
集合的泛型非常有用,因为它们允许编译时类型安全.这有用的原因有以下几点:
在检索值时不需要铸造.这不仅具有性能优势,还消除了运行时出现转换异常的风险
将值类型添加到非泛型列表(如ArrayList)时,必须将值设置为框.这意味着它们存储为引用类型.这也意味着不仅值被存储在内存中,而且对它的引用也是如此,因此使用了比necessery更多的内存.使用通用列表时,可以消除此问题.
通用类
通用类可用于重用不同类型的公共代码.以一个简单的非通用工厂类为例:
public class CatFactory
{
public Cat CreateCat()
{
return new Cat();
}
}
Run Code Online (Sandbox Code Playgroud)
我可以使用泛型类为(几乎)任何类型提供工厂:
public class Factory<T> where T : new()
{
public T Create()
{
return new T();
}
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我在类型参数T上放置了new()的泛型类型约束.这要求泛型类型包含一个无参数的构造函数,这使我能够在不知道类型的情况下创建实例.
只是因为你说你是瑞典人,我想我会举一个整合宜家家具的例子.你的套装沙发是北美的一种感染,所以我想我会回馈一些东西:)想象一个代表一个特殊的椅子和桌子套件的课程.为了保持真实,我甚至会使用无意义的瑞典语言同音异义词:
// interface for included tools to build your furniture
public interface IToolKit {
string[] GetTools();
}
// interface for included parts for your furniture
public interface IParts {
string[] GetParts();
}
// represents a generic base class for IKEA furniture kit
public abstract class IkeaKit<TContents> where TContents : IToolKit, IParts, new() {
public abstract string Title {
get;
}
public abstract string Colour {
get;
}
public void GetInventory() {
// generic constraint new() lets me do this
var contents = new TContents();
foreach (string tool in contents.GetTools()) {
Console.WriteLine("Tool: {0}", tool);
}
foreach (string part in contents.GetParts()) {
Console.WriteLine("Part: {0}", part);
}
}
}
// describes a chair
public class Chair : IToolKit, IParts {
public string[] GetTools() {
return new string[] { "Screwdriver", "Allen Key" };
}
public string[] GetParts() {
return new string[] {
"leg", "leg", "leg", "seat", "back", "bag of screws" };
}
}
// describes a chair kit call "Fnood" which is cyan in colour.
public class Fnood : IkeaKit<Chair> {
public override string Title {
get { return "Fnood"; }
}
public override string Colour {
get { return "Cyan"; }
}
}
public class Snoolma : IkeaKit<Chair> {
public override string Title {
get { return "Snoolma "; }
}
public override string Colour {
get { return "Orange"; }
}
}
Run Code Online (Sandbox Code Playgroud)
好的,现在我们已经掌握了如何构建一些廉价家具所需的所有东西:
var fnood = new Fnood();
fnood.GetInventory(); // print out tools and components for a fnood chair!
Run Code Online (Sandbox Code Playgroud)
(是的,缺乏说明和椅子套件中的三条腿是故意的.)
希望这有助于以一种厚颜无耻的方式.
如果有一个 List 对象(非泛型),则可以将任何可以转换为 Object 的内容存储到其中,但无法在编译时知道从中得到什么类型的内容。相比之下,如果有一个泛型 List<Animal>,则可以存储到其中的唯一内容是 Animal 或其派生类,并且编译器可以知道从中提取的唯一内容将是 Animal。因此,编译器可以允许将内容从 List 中取出并直接存储到 Animal 类型的字段中,而不需要运行时类型检查。
此外,如果泛型类的泛型类型参数恰好是值类型,则使用泛型类型可以消除在 Object 之间进行转换的需要,这一过程称为“装箱”,它将值类型实体转换为引用类型对象; 装箱有点慢,有时会改变值类型对象的语义,因此最好尽可能避免。
请注意,尽管 SomeDerivedClass 类型的对象可以替代 TheBaseClass,但一般来说,GenericSomething<SomeDerivedClass> 不能替代 GenericSomething<TheBaseClass>。问题是,如果可以用 List<Giraffe> 替换 List<Zebra>,则可以将 List<Zebra> 传递给期望获取 List<Giraffe> 并在其中存储大象的例程。不过,有几种情况是允许可替代性的:
此外,如果接口所做的唯一事情就是按值接受该类型的参数,则可以声明接口来声明“in”类型参数。食动物者可以用食长颈鹿者来代替,因为它能够吃掉所有动物,因此也能够吃掉所有长颈鹿。这样的接口对于那些参数是“逆变的”。