C# 泛型C中的无界类型参数#

C# 泛型C中的无界类型参数#,c#,generics,C#,Generics,我是泛型新手,我从一开始就学习泛型 我无法理解以下关于无界类型参数的要点 没有约束的类型参数,例如公共类SampleClass{}中的T,称为无界类型参数。无界类型参数具有以下规则: =和==运算符不能使用,因为没有保证 具体类型参数将支持这些运算符 您可以与null进行比较。如果将无界参数与 null,如果类型参数为 值类型 我没有发现任何上述观点的例子。如果有人给我举个例子来理解要点,那就太好了 注意:我的问题是关于的使用=和==运算符。。。为什么我们不能在无界类型中使用这些运算符,如果

我是泛型新手,我从一开始就学习泛型

我无法理解以下关于无界类型参数的要点

没有约束的类型参数,例如
公共类SampleClass{}
中的
T
,称为无界类型参数。无界类型参数具有以下规则:

  • =
    ==
    运算符不能使用,因为没有保证 具体类型参数将支持这些运算符
  • 您可以与
    null
    进行比较。如果将无界参数与
    null
    ,如果类型参数为 值类型
我没有发现任何上述观点的例子。如果有人给我举个例子来理解要点,那就太好了


注意:我的问题是关于
的使用=
==
运算符。。。为什么我们不能在无界类型中使用这些运算符,如果将无界参数与
null
进行比较,为什么总是返回
false
,类型参数可以有约束,例如:
其中t:BaseClass
。这意味着T必须从
基类
继承。如果类型参数没有此类约束,则称之为unbounded。

您引用的文档中有两点:

那个!=无法使用and==运算符,因为无法保证具体类型参数将支持这些运算符

这意味着编译器无法知道类型
t
具有运算符
=
=
SampleClass
可以工作,但是如果
MyType
没有实现操作符,
SampleClass
可能无法工作。由于
T
是无界的,这意味着编译器无法知道预期的结果,因此必须采用最严格的情况

您可以将其与null进行比较。如果将无界参数与null进行比较,则如果类型参数是值类型,则比较将始终返回false

这只是指出,您可以将其与null进行比较,但是如果
T
是不可为null的类型,那么它总是返回false。考虑以下事项:

int i = 0;
if (null == i)
{
}

这将生成一个编译器警告,因为没有任何值可以赋予
i
使表达式
为true

让我们假设这是可能的:

public class C
{
     public bool AreEqual<T>(T first, T second)
     {
           return first == second;
     }
}
值类型没有
==
的实现,我们不能遵从
对象。ReferenceEquals
,因为这也是一种值类型。这就是为什么编译器不允许您这样做

我的问题是关于!=and==运算符。。。为什么我们不能在无界类型中使用这些运算符

他们是什么意思?通常
=
=
表示“不等于”和“等于”,但其确切含义取决于它们是值类型还是引用类型(以及它们是否重载了这些运算符,但这也不适用于许多有界类型)。不受限制,至少是那些
中的一个=
==
没有意义

如果将无界参数与null进行比较,为什么总是返回false呢

你看错了。你刚才所说和引用的是:

如果类型参数是值类型,则比较将始终返回false。[我的重点]

这实际上是不正确的,在这种情况下,可空值类型可以返回
true

public class Test<T>
{
  public bool IsNull(T val)
  {
     return val == null;
  }
}
当为不可为空的值类型的
T
进行JIT时,则与代码相同:

public string CallToString(T val)
{
  return val.ToString();
}
因为抖动知道第一个分支永远不会被击中。同样地考虑<代码>枚举。此方法对可为null类型的空序列返回
null
,否则抛出异常。对于特定的重写,这很简单:
Enumerable.Max(此IEnumerable源)
例如,在这种情况下,代码将返回null,而
Enumerable.Max(此IEnumerable源)
将抛出代码。但对于一般情况,它需要涵盖这两种情况。它这样做:

public static TSource Max<TSource>(this IEnumerable<TSource> source)
{
  if (source == null) throw Error.ArgumentNull("source");
  Comparer<TSource> comparer = Comparer<TSource>.Default;
  TSource value = default(TSource);
  if (value == null)
  {
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
      do
      {
        if (!e.MoveNext()) return value;
        value = e.Current;
      } while (value == null);
      while (e.MoveNext())
      {
        TSource x = e.Current;
        if (x != null && comparer.Compare(x, value) > 0) value = x;
      }
    }
  }
  else
  {
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
      if (!e.MoveNext()) throw Error.NoElements();
      value = e.Current;
      while (e.MoveNext())
      {
        TSource x = e.Current;
        if (comparer.Compare(x, value) > 0) value = x;
      }
    }
  }
  return value;
}
如果该类型是不可为null的值类型,则与jitting相同:

public static TSource Max<TSource>(this IEnumerable<TSource> source)
{
  if (source == null) throw Error.ArgumentNull("source");
  Comparer<TSource> comparer = Comparer<TSource>.Default;
  TSource value = null;
  using (IEnumerator<TSource> e = source.GetEnumerator())
  {
    do
    {
      if (!e.MoveNext()) return value;
      value = e.Current;
    } while (value == null);
    while (e.MoveNext())
    {
      TSource x = e.Current;
      if (x != null && comparer.Compare(x, value) > 0) value = x;
    }
  }
  return value;
}
public static TSource Max<TSource>(this IEnumerable<TSource> source)
{
  if (source == null) throw Error.ArgumentNull("source");
  Comparer<TSource> comparer = Comparer<TSource>.Default;
  TSource value = default(TSource);
  using (IEnumerator<TSource> e = source.GetEnumerator())
  {
    if (!e.MoveNext()) throw Error.NoElements();
    value = e.Current;
    while (e.MoveNext())
    {
      TSource x = e.Current;
      if (comparer.Compare(x, value) > 0) value = x;
    }
  }
  return value;
}
publicstatictsourcemax(此IEnumerable源)
{
if(source==null)抛出错误.ArgumentNull(“source”);
Comparer=Comparer.Default;
TSource值=默认值(TSource);
使用(IEnumerator e=source.GetEnumerator())
{
如果(!e.MoveNext())抛出错误.NoElements();
值=e.电流;
while(如MoveNext())
{
t电源x=e.电流;
如果(比较器比较(x,值)>0)值=x;
}
}
返回值;
}

因此,不可空值类型和
null
之间的
=
总是
false
(和
!=
总是
true
)这一事实不仅仅是一个限制,它实际上还可以帮助我们以不同的方式覆盖可空类型和不可空类型,抖动在移除特定情况下未使用的分支时会表现得很好。

我会尝试让您知道。。我们可以用
Equals()
来代替
=
Equals
对一个没有实现
IEquatable
的值类型,它将调用
对象。ReferenceEquals
,它将显示为框。@Khurram将等式转换为不相关。请注意,您引用的文档实际上是不正确的<当
T
是像
int?
这样的可空值类型时,code>default(T)==null
返回true。
public static TSource Max<TSource>(this IEnumerable<TSource> source)
{
  if (source == null) throw Error.ArgumentNull("source");
  Comparer<TSource> comparer = Comparer<TSource>.Default;
  TSource value = null;
  using (IEnumerator<TSource> e = source.GetEnumerator())
  {
    do
    {
      if (!e.MoveNext()) return value;
      value = e.Current;
    } while (value == null);
    while (e.MoveNext())
    {
      TSource x = e.Current;
      if (x != null && comparer.Compare(x, value) > 0) value = x;
    }
  }
  return value;
}
public static TSource Max<TSource>(this IEnumerable<TSource> source)
{
  if (source == null) throw Error.ArgumentNull("source");
  Comparer<TSource> comparer = Comparer<TSource>.Default;
  TSource value = default(TSource);
  using (IEnumerator<TSource> e = source.GetEnumerator())
  {
    if (!e.MoveNext()) throw Error.NoElements();
    value = e.Current;
    while (e.MoveNext())
    {
      TSource x = e.Current;
      if (comparer.Compare(x, value) > 0) value = x;
    }
  }
  return value;
}