gpt4 book ai didi

c# - 构造/制作通用类型并将类型约束转换为结构作为基础类型的约束

转载 作者:行者123 更新时间:2023-11-30 12:26:30 26 4
gpt4 key购买 nike

通常我们不能约束类型参数 T派生自密封类型(例如 struct 类型)。这将毫无意义,因为只有一种类型适合,因此不需要泛型。所以约束如下:

where T : string

或:

where T : DateTime

是非法的,这是有充分理由的。

但是,当约束到另一个类型参数时,当另一个类型参数被“替换”为实际类型(碰巧是密封的)时,有时会发生这种情况。考虑类:

abstract class ExampleBase<TFromType>
{
internal abstract void M<TFromMethod>(TFromMethod value) where TFromMethod : TFromType;
}

这是很无辜的。在具体化中:

class ExampleOne : ExampleBase<string>
{
internal override void M<TFromMethod>(TFromMethod strangeString)
{
var a = string.IsNullOrEmpty(strangeString);
Console.WriteLine(a);
var b = strangeString.Substring(10, 2);
Console.WriteLine(b);
}
}

我们制作 TFromType等于 string .这可能是有意义的。除M<>以外的其他成员.但是M<>本身仍然可以使用: 代码:

  var e1 = new ExampleOne();
e1.M("abcdefghijklmnopqrstuvwxyz");

将运行并写入:

Falsekl

to the console. So the constraint essentially became where TFromMethod : string, but things were still fine.

This question is about what happens if TFromType is a value type. So this time we do:

class ExampleTwo : ExampleBase<DateTime>
{
internal override void M<TFromMethod>(TFromMethod strangeDate)
{
// var c = DateTime.SpecifyKind(strangeDate, DateTimeKind.Utc); // will not compile
// var d = strangeDate.AddDays(66.5); // will not compile

var e = string.Format(CultureInfo.InvariantCulture, "{0:D}", strangeDate); // OK, through boxing
Console.WriteLine(e);
var f = object.ReferenceEquals(strangeDate, strangeDate);
Console.WriteLine("Was 'strangeDate' a box? " + f);
}
}

那么为什么来自 c 的电话呢?和 d不允许声明?毕竟strangeDate具有编译时类型 TFromMethod这被限制为 DateTime .所以肯定strangeDate隐式地是一个 DateTime ?毕竟,这适用于 string (class ExampleOne 以上)。

我更喜欢引用官方 C# 语言规范中相关位置的答案。

请注意,在尝试添加 d 时, 输入 strangeDate.Ad ... 使 IntelliSense(Visual Studio 的自动完成器)得出 DateTime 的所有可访问实例成员的列表。 , 很明显 IntelliSense 认为 d 中的调用应该是合法的!

当然是在c之后和 d已经被注释掉了,我们可以使用ExampleTwo (使用 ef ),以及代码:

  var e2 = new ExampleTwo();
e2.M(new DateTime(2015, 2, 13));

运行并写出:

Friday, 13 February 2015Was 'strangeDate' a box? False

最佳答案

引用 C# 5.0 规范:

6.1.10 Implicit conversions involving type parameters

The following implicit conversions exist for a given type parameter T:

  • From T to its effective base class C, from T to any base class of C, and from T to any interface implemented by C. [...]

  • [...]

10.1.5 Type parameter constraints

The effective base class of a type parameter T is defined as follows:

  • [...]
  • If T has no class-type constraint but has one or more type-parameter constraints, its effective base class is the most encompassed type (§6.4.2) in the set of effective base classes of its type-parameter constraints. The consistency rules ensure that such a most encompassed type exists.
  • [...]

For the purpose of these rules, if T has a constraint V that is a value-type, use instead the most specific base type of V that is a class-type. This can never happen in an explicitly given constraint, but may occur when the constraints of a generic method are implicitly inherited by an overriding method declaration or an explicit implementation of an interface method.

These rules ensure that the effective base class is always a class-type.

换句话说,给定一个 where U : T 约束 T = stringU 的有效基类是 字符串。给定一个 where U : T 约束条件 T = DateTimeU 的有效基类不是 DateTime,但是 ValueType。类型参数唯一相关的隐式转换是从类型参数类型到其有效基类。

这似乎确实会导致一些相当奇怪的行为,正如您所发现的那样,但这一定是一个有意识的决定,因为它已被明确说明以您所看到的方式行事。

我猜想使这项工作在编译器中造成困难,在某些情况下编译器假定它在这种情况下处理引用类型,并且使它工作只有最小的好处。不过,仅此而已:一个猜测。

关于c# - 构造/制作通用类型并将类型约束转换为结构作为基础类型的约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28500153/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com