老实说,我不知道他们叫什么.我一直无法在互联网上找到文章.
所以我明白你可以这样做:
public struct Pair<T, U>
{
public readonly T Value1;
public readonly U Value2;
public Pair(T fst, U snd)
{
this.Value1 = fst;
this.Value2 = snd;
}
public override String ToString()
{
return "(" + Value1 + ", " + Value2 + ")";
}
public Pair<U, T> Swap()
{
return new Pair<U, T>(Value2, Value1);
}
}
Run Code Online (Sandbox Code Playgroud)
它可能是一个class而不是一个struct.
但我很困惑,出于什么目的?某种性能提升?据我所知,您可以使用这些东西(抱歉,这是什么名称?)来保存值.但是你不会总是知道它应该拥有什么样的数据吗?例如:如果您需要存储产品,则只需制作产品类.当然,你知道它需要掌握什么样的数据,因为你正在设计代码.
所以是的,我想我的问题是:这个的目的是什么,与普通物体相比有什么优势; 您指定了更多
我想我不清楚.我也想知道:有没有充分的理由去创造像上面那样的东西?例如,一个更具体的对象,例如将产品数据存储在产品对象中,而不是一些可以接收所有内容的通用对象.
新:更多文本:另外,你怎么能处理完全通用的错误编码?当我不知道我必须处理什么样的数据类型时,我担心会进行任何类型的数学操作或实际上任何操作.如果它需要我为所有数据类型编写错误处理,那么我真的看不到这些通用参数的优点.
假设您有两种情况,代码是相同的,除了代码中引用的类型之一是不同的.
能够将代码编写一次,然后在两种情况下使用相同的代码都不是很有用吗?例如,容器类就像List- 应该清楚的是,List每次要在其中存储特定类型时,必须编写不同的类会很麻烦.
它们被称为类型参数,需要参数的类型是泛型类型.
一个非常流行的数据结构是Dictionary<TKey, TValue>.它将键映射到值,因此您可以查找给定键的值.例如,密钥可能是"姓氏",值可能是"电话号码" - 在这种情况下,两者都是字符串类型(电话号码并不总是数字).
循环遍历a的内容时Dictionary,它存储的每个项目都是一对.在标准类中,类型是KeyValuePair<TKey, TValue>:
for (var pair in myDict)
{
Console.WriteLine(pair.Key + " maps to " + pair.Value);
}
Run Code Online (Sandbox Code Playgroud)
目的是通用性.通常,您有一个类,其行为并不真正取决于它所使用的类型.
而不是Pair考虑.NET类List<T>.它存储了某些类型的列表.该列表没有,也不应该关心它存储的类型.它只需要保证只能存储该类型.
A List<string>允许我存储字符串.A List<int>允许我存储整数.
如果我们没有泛型,我们必须抛弃类型安全,并使用一个只存储Object的类的List类,但是没有什么可以阻止我存储Apple在Bananas 列表中.
或者我们可以List为我们需要存储的每种类型编写一个新类.我们可以有ListOfApples,ListOfBananas,ListOfInts等.
我认为泛型提供了一个更好的解决方案.
这个Pair例子可能不太明显,因为often如果我们需要精确存储两个值,那是因为它们有一些明确的关系,应该通过创建一个特定的对象来表示.但有时,他们没有.有时它们只是"第一价值"和"第二价值".也许你有一个只返回两个值的函数.返回一个Pair<T1, T2,比返回一个值并通过一个out参数处理另一个更容易.
你经常不需要一双,没有.但是如果你真的需要"一种方法在单个对象中存储两个不同类型的值",如果没有与之关联的真实行为,那么一个Pair类很好地代表了它.然后,为什么不通过允许类型更改来使其可重用?
另外,你怎么能处理完全通用的错误编码?当我不知道我必须处理什么样的数据类型时,我担心会进行任何类型的数学操作或实际上任何操作.如果它需要我为所有数据类型编写错误处理,那么我真的看不到这些通用参数的优点.
简单:.NET不允许你这样做.在你的Pair示例中,如果你尝试使用一个不保证可用的函数,编译器会抱怨.在您的情况下,您将只能使用Object基类上定义的函数(当然,通用函数和类也适用于任何类型).
因此,您不能对这些泛型类型使用任何类型的数学操作.除了存储它们并传递它们(和调用.ToString())之外,你不能用它们做更多的事情.但有时候,你不需要更多的东西.例如,如果您只是创建一个List类,或者一个Pair.
您还可以指定约束,将其缩小一点.例如:
void DoStuffWithStream(T arg) where T : Stream
{
// in this function that T is some type derived from Stream, so we can use all methods that would work on a Stream.
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试使用a调用它,这将产生编译错误int,但是将适用于所有各种Stream子类.现在我对课程了解得更多,所以我将能够有意义地进行一些操作.
但是回到错误处理,你需要在List课堂上处理什么错误?不会发生很多错误.你有一个类,它的工作是存储一些未知(但固定)类型的可变数量的对象.它可以插入新对象(可能会抛出内存不足异常),并且可以检索对象.它可以让我们搜索对象,当然,当我们搜索到的东西找不到时,我们可能会遇到错误情况.但基本上就是这样.没有特定于泛型类型的错误处理.为什么会这样?我们不会对我们存储的对象执行任何类型特定的操作,因此它们实际上没有机会抛出任何特定于类型的错误.