标签: generic-variance

如何在C#4.0中实现通用协方差和Contra-variance?

我没有参加PDC 2008,但我听到一些消息称C#4.0被宣布支持Generic协方差和反差异.也就是说,List<string>可以分配给List<object>.怎么会这样?

在Jon Skeet的C#深度书中,解释了为什么C#泛型不支持协方差和反方差.它主要用于编写安全代码.现在,C#4.0改为支持它们.它会带来混乱吗?

有人知道有关C#4.0的细节可以给出一些解释吗?

c# covariance contravariance generic-variance c#-4.0

106
推荐指数
2
解决办法
4万
查看次数

为什么C#不支持变体泛型类?

拿这个小LINQPad示例:

void Main()
{
    Foo<object> foo = new Foo<string>();
    Console.WriteLine(foo.Get());
}

class Foo<out T>
{
    public T Get()
    {
        return default(T);
    }
}
Run Code Online (Sandbox Code Playgroud)

它无法使用此错误进行编译:

方差修饰符无效.只能将接口和委托类型参数指定为变量.

我没有看到代码的任何逻辑问题.一切都可以静态验证.为什么不允许这样做?它是否会导致语言不一致,或者由于CLR的限制而被认为实施起来太昂贵了?如果是后者,我作为开发人员应该知道什么是上述限制?

考虑到接口支持它,我希望从逻辑上遵循该类支持.

c# generics class generic-variance

19
推荐指数
1
解决办法
1680
查看次数

自定义Autofac的组件分辨率/具有通用协同/逆变的问题

首先,抱歉模糊的问题标题.我无法想出更精确的一个.

鉴于以下类型:

                                                     { TCommand : ICommand }
       «interface»                   «interface»    /
      +-----------+         +----------------------/----+
      | ICommand  |         | ICommandHandler<TCommand> |
      +-----------+         +---------------------------+
            ^               | Handle(command: TCommand) |
            |               +---------------------------+
            |                              ^
            |                              |
      +------------+            +-------------------+
      | FooCommand |            | FooCommandHandler |
      +------------+            +-------------------+
            ^
            |
   +-------------------+
   | SpecialFooCommand |
   +-------------------+
Run Code Online (Sandbox Code Playgroud)

我想编写一个Dispatch接受任何命令并将其发送到适当的方法ICommandHandler<>.我认为使用DI容器(Autofac)可能会大大简化从命令类型到命令处理程序的映射:

void Dispatch<TCommand>(TCommand command) where TCommand : ICommand
{
    var handler = autofacContainer.Resolve<ICommandHandler<TCommand>>();
    handler.Handle(command);
}
Run Code Online (Sandbox Code Playgroud)

假设DI容器知道上面显示的所有类型.现在我打电话给:

Dispatch(new SpecialFooCommand(…));
Run Code Online (Sandbox Code Playgroud)

实际上,这将导致Autofac抛出一个ComponentNotRegisteredException,因为没有ICommandHandler<SpecialFooCommand>可用的.

然而,理想情况下,我仍然希望SpecialFooCommand由最接近匹配的命令处理程序处理,即.通过FooCommandHandler在上面的例子. …

c# customization resolution autofac generic-variance

18
推荐指数
2
解决办法
1913
查看次数

C#4.0中的通用差异

C#4.0中的通用差异已经实现,可以在没有异常的情况下编写以下内容(这将在C#3.0中发生):

 List<int> intList = new List<int>();
 List<object> objectList = intList; 
Run Code Online (Sandbox Code Playgroud)

[非功能性示例:请参阅Jon Skeet的回答]

我最近参加了一个会议,其中乔恩斯基特给通用差异的很好的概述,但我不知道我完全得到它-我理解的重要性inout关键词,当谈到禁忌和协变,但我我很好奇幕后发生的事情.

执行此代码时CLR会看到什么?是隐式转换List<int>List<object>或者它是否只是构建在我们现在可以在派生类型之间转换为父类型?

出于兴趣,为什么在以前的版本中没有引入这个,主要的好处是什么 - 即真实世界的使用?

关于Generic Variance的这篇文章的更多信息(但问题非常过时,寻找真实的,最新的信息)

.net-4.0 covariance contravariance generic-variance c#-4.0

16
推荐指数
3
解决办法
3200
查看次数

如何确定类型参数的方差?

灵感来自现实世界中Scala的共同和逆转的例子,我认为一个更好的问题是:

在设计库时,在确定类型参数是应该是协变还是逆变时,是否应该问自己一组特定的问题?或者你应该让一切都不变,然后根据需要改变?

types scala covariance contravariance generic-variance

11
推荐指数
1
解决办法
590
查看次数

与Func <in T1,out TResult>作为参数的Co/contravariance

假设我有一个界面如

public interface IInterface<in TIn, out TOut> {
  IInterface<TIn, TOut> DoSomething(TIn input);
}
Run Code Online (Sandbox Code Playgroud)

TIn禁忌 -variant,并TOut合作 -variant.

现在,我希望调用者能够指定一些要在输入值上执行的函数,所以天真地我会在接口中添加以下方法:

IInterface<TIn, TOut> DoSomethingWithFunc(Func<TIn, TOut> func);
Run Code Online (Sandbox Code Playgroud)

哪......不起作用.TIn现在需要协变,TOut逆变.

我理解,我不能使用协变泛型类型作为方法的输入,但我想我可以在嵌套泛型类型中使用它们,它本身指定了variance(Func<in T1, out TResult>).

我尝试使用co/contravariant类型创建一个新的委托类型,并更改接口以接受此类型的参数,但无效(相同的错误).

public delegate TOut F<in TDlgIn, out TDlgOut>(TDlgIn input);

public interface IInterface<in TIn, out TOut> {
  IInterface<TIn, TOut> DoSomethingWithFunc(F<TIn, TOut> func);
}
Run Code Online (Sandbox Code Playgroud)

我有办法让编译器开心吗?这是否可能(例如使用其他嵌套类型或其他通用参数)?如果没有,为什么不呢?

.net c# generics generic-variance

11
推荐指数
1
解决办法
365
查看次数

为什么类类型参数的方差必须与其方法的返回/参数类型参数的方差相匹配?

以下提出了投诉:

interface IInvariant<TInv> {}
interface ICovariant<out TCov> {
    IInvariant<TCov> M(); // The covariant type parameter `TCov'
                          // must be invariantly valid on
                          // `ICovariant<TCov>.M()'
}
interface IContravariant<in TCon> {
    void M(IInvariant<TCon> v); // The contravariant type parameter
                                // `TCon' must be invariantly valid
                                // on `IContravariant<TCon>.M()'
}
Run Code Online (Sandbox Code Playgroud)

但我无法想象这不会是类型安全的.(剪断*)这是不允许这样做的原因,还是有其他违反类型安全的情况我不知道?


*我最初的想法确实令人费解,但尽管如此,答案非常彻底,@ Theodoros Chatzigiannakis甚至以令人印象深刻的准确性解剖了我的初步假设.

除了回顾过去的好评之外,我意识到我错误地认为类型签名ICovariant::M仍然是一个Func<IInvariant<Derived>>当它ICovariant<Derived>被分配给a时ICovariant<Base>.然后,该分配MFunc<IInvariant<Base>>看起来罚款来自未来ICovariant<Base>,但当然会是非法的.为什么不禁止最后这个显然是非法的演员?(所以我认为)

正如埃里克·利珀特(Eric Lippert)所指出的那样,我觉得这种错误和切向猜测会减少这个问题,但出于历史目的,这个被剪切的部分:

对我来说最直观的解释是,以ICovariant协变为例,TCov …

c# generics generic-variance

10
推荐指数
2
解决办法
387
查看次数

为什么kotlin不允许协变mutablemap成为委托?

我是Kotlin的新手.当我在地图中学习存储属性时.我尝试以下用法.

class User(val map: MutableMap<String, String>) {
    val name: String by map
}
Run Code Online (Sandbox Code Playgroud)

class User(val map: MutableMap<String, in String>) {
    val name: String by map
}
Run Code Online (Sandbox Code Playgroud)

class User(val map: MutableMap<String, out String>) {
    val name: String by map
}
Run Code Online (Sandbox Code Playgroud)

前两个都是工作,最后一个都失败了.使用out修饰符,字节码getName如下:

  public final java.lang.String getName();
     0  aload_0 [this]
     1  getfield kotl.User.name$delegate : java.util.Map [11]
     4  astore_1
     5  aload_0 [this]
     6  astore_2
     7  getstatic kotl.User.$$delegatedProperties : kotlin.reflect.KProperty[] [15]
    10  iconst_0
    11  aaload
    12  astore_3 …
Run Code Online (Sandbox Code Playgroud)

delegates jvm generic-variance kotlin

7
推荐指数
1
解决办法
357
查看次数

C#4.0方差可以帮我调用一个带有upcast的基类构造函数吗?

我正在阅读关于泛型方差的一些内容,但我还没有完全理解它,但我想知道它是否可能产生类似下面的内容?

class A<T> { }

class B { }

class C : B { }

class My1  {
    public My1(A<B> lessDerivedTemplateParameter)
    {
    }
}

class My2 : My1 {
    public My2(A<C> moreDerivedTemplateParameter)
        : base(moreDerivedTemplateParameter) // <-- compile error here, cannot convert
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

c# generic-variance

6
推荐指数
1
解决办法
164
查看次数

功能类型之间的子类型

在课程函数式编程课程中,我遇到了一个微妙的概念.

如果A2 <:A1B1 <:B2,则(A1 => B1)<:( A2 => B2)

理由

  • 当我们将参数传递给A2并且由于子类型关系时,我们可以将相同的参数传递给A1.
  • 然后应用函数A1 => B1
  • 然后该函数给出B1,因为子类型符合B2

如果我们为此画一个维恩图,

  • 图1 图1

  • 图2 图2

    • 这是正确的图表?
    • 如何使用维恩图解释结果?

参考:Youtube视频

谢谢

functional-programming scala generic-variance

6
推荐指数
1
解决办法
257
查看次数