标签: contravariance

我只能用"as"来施放逆变代表

我正在尝试施放逆变委托但由于某种原因我只能使用"as"运算符.

interface MyInterface { }
delegate void MyFuncType<in InType>(InType input);

class MyClass<T> where T : MyInterface
{
    public void callDelegate(MyFuncType<MyInterface> func)
    {
        MyFuncType<T> castFunc1 = (MyFuncType <T>) func; //Error
        MyFuncType<T> castFunc2 = func as MyFuncType<T>; 
        MyFuncType<T> castFunc3 = func is MyFuncType<T> ? (MyFuncType<T>)func : (MyFuncType<T>)null; //Error
    }
}
Run Code Online (Sandbox Code Playgroud)

castFunc2工作正常,但castFunc1和castFunc3导致错误:

Cannot convert type 'delegateCovariance.MyFuncType<myNamespace.MyInterface>' to myNamespace.MyFuncType<T>'
Run Code Online (Sandbox Code Playgroud)

上为运营商MSDN文章指出,castFunc2和castFunc3"等价于"所以我不明白怎么只有一个可能会导致错误.另一部令我困惑的是将MyInterface从接口更改为类可以消除错误.

任何人都可以帮我理解这里发生了什么?谢谢!

c# generics casting .net-4.0 contravariance

28
推荐指数
1
解决办法
721
查看次数

如何在Java泛型中使用逆变?

在Java中,协方差允许API设计者指定实例可以被概括为某种类型或任何该类型的子类型.例如:

List<? extends Shape> shapes = new ArrayList<Circle>(); 
// where type Circle extends Shape
Run Code Online (Sandbox Code Playgroud)

反方差则是另一种方式.它允许我们指定实例可以概括为某种类型或超类型.

List<? super Shape> shapes = new ArrayList<Geometry>();
// where Shape extends Geometry
Run Code Online (Sandbox Code Playgroud)

Java泛型的逆变是如何有用的?你什么时候选择使用它?

java generics contravariance

25
推荐指数
3
解决办法
6137
查看次数

什么<在TFrom,out TTo>是什么意思?

Resharper建议改变

interface IModelMapper<TFrom, TTo>
{
    TTo Map(TFrom input);
}
Run Code Online (Sandbox Code Playgroud)

interface IModelMapper<in TFrom, out TTo>
Run Code Online (Sandbox Code Playgroud)

所以我调查了一下,结束了阅读这篇文章(通过维基百科的文章找到)和更多的谷歌.

我仍然不确定这对我的申请意味着什么,所以我很想接受这个建议.这种改变会带来什么好处,我不考虑忽视这个建议?

更明确的是,我为什么要接受它?

c# generics covariance contravariance

25
推荐指数
1
解决办法
2258
查看次数

为什么协方差不适用于泛型方法

假设我有接口和类:

public interface ITree {}
public class Tree : ITree {}
Run Code Online (Sandbox Code Playgroud)

由于IEnumerable<T>协变,下面的代码行成功编译:

IEnumerable<ITree> trees = new List<Tree>();
Run Code Online (Sandbox Code Playgroud)

但是当我把它放入通用方法时:

public void Do<T>() where T : ITree
{
     IEnumerable<ITree> trees = new List<T>();
}
Run Code Online (Sandbox Code Playgroud)

我从编译器得到编译错误:

错误1无法将类型'System.Collections.Generic.List'隐式转换为'System.Collections.Generic.IEnumerable'.存在显式转换(您是否缺少演员?)D:\ lab\Lab.General\Lab.General\Program.cs 83 40 Lab.General

为什么协方差在这种情况下不起作用?

c# covariance contravariance c#-4.0

23
推荐指数
1
解决办法
1987
查看次数

为什么TEventArgs在.NET生态系统的标准事件模式中没有逆变?

在.NET中了解有关标准事件模型的更多信息时,我发现在引入C#中的泛型之前,处理事件的方法由此委托类型表示:

//
// Summary:
//     Represents the method that will handle an event that has no event data.
//
// Parameters:
//   sender:
//     The source of the event.
//
//   e:
//     An object that contains no event data.
public delegate void EventHandler(object sender, EventArgs e);
Run Code Online (Sandbox Code Playgroud)

但是在C#2中引入泛型之后,我认为这个委托类型是使用泛型重写的:

//
// Summary:
//     Represents the method that will handle an event when the event provides data.
//
// Parameters:
//   sender:
//     The source of the event.
//
//   e:
// …
Run Code Online (Sandbox Code Playgroud)

.net c# contravariance .net-core

23
推荐指数
1
解决办法
918
查看次数

为什么C#(4.0)不允许泛型类的共同和逆变?

这种限制的真正原因是什么?这只是必须完成的工作吗?概念上难吗?这不可能吗?

当然,人们不能在字段中使用类型参数,因为它们总是读写.但这不是答案,可以吗?

这个问题的原因是我在C#4上写了一篇关于方差支持的文章,我觉得我应该解释为什么它仅限于委托和接口.只是为了逆转举证责任.

更新: 埃里克问了一个例子.

怎么样(不知道这是否有意义,但是:-))

public class Lookup<out T> where T : Animal {
  public T Find(string name) {
    Animal a = _cache.FindAnimalByName(name);
    return a as T;
  }
}

var findReptiles = new Lookup<Reptile>();
Lookup<Animal> findAnimals = findReptiles;
Run Code Online (Sandbox Code Playgroud)

在一个类中拥有它的原因可能是类本身中保存的缓存.请不要将您的不同类型的宠物命名为相同!

顺便说一句,这让我想到了C#5.0中的可选类型参数 :-)

更新2:我没有声称CLR和C#应该允许这个.只是想了解是什么原因导致它没有.

c# generics covariance contravariance c#-4.0

22
推荐指数
2
解决办法
4379
查看次数

如何找到两种类型之间最佳拟合的最小协变类型?

IsAssignableFrom方法返回一个布尔值,表示一种类型是否可以从另一种类型分配.

怎能不只有他们分配的测试对方,但也知道了最低协变,以获得最佳类型?

考虑以下示例(C#4.0)

  • // method body of Func is irrelevant, use default() instead
    Func<char[]> x = default(Func<char[]>);
    Func<int[]> y = default(Func<int[]>);
    
    Func<Array> f = default(Func<Array>);
    Func<IList> g = default(Func<IList>);
    
    g=x;
    g=y;
    
    y=x; // won't compile
    x=y; // won't compile
    
    // following two are okay; Array is the type for the covariance
    f=x; // Array > char[] -> Func<Array> > Func<char[]> 
    f=y; // Array > int[] -> Func<Array> > Func<int[]> 
    
    // following …
    Run Code Online (Sandbox Code Playgroud)

c# types covariance contravariance

21
推荐指数
1
解决办法
1201
查看次数

如何在不破坏封装的情况下返回对RefCell内部内容的引用?

我有一个内部可变性的结构.

use std::cell::RefCell;

struct MutableInterior {
    hide_me: i32,
    vec: Vec<i32>,
}
struct Foo {
    //although not used in this particular snippet,
    //the motivating problem uses interior mutability
    //via RefCell.
    interior: RefCell<MutableInterior>,
}

impl Foo {
    pub fn get_items(&self) -> &Vec<i32> {
        &self.interior.borrow().vec
    }
}

fn main() {
    let f = Foo {
        interior: RefCell::new(MutableInterior {
            vec: Vec::new(),
            hide_me: 2,
        }),
    };
    let borrowed_f = &f;
    let items = borrowed_f.get_items();
}
Run Code Online (Sandbox Code Playgroud)

产生错误:

error[E0597]: borrowed value does not live long enough
  --> …
Run Code Online (Sandbox Code Playgroud)

encapsulation contravariance mutability rust interior-mutability

21
推荐指数
3
解决办法
2487
查看次数

如果我<D>通过方差转换可以转换为I <B>,我是否<D>重新实现I <B>?

interface ICloneable<out T>
{
    T Clone();
}

class Base : ICloneable<Base>
{
    public Base Clone() { return new Base(); }
}

class Derived : Base, ICloneable<Derived>
{
    new public Derived Clone() { return new Derived(); }
}
Run Code Online (Sandbox Code Playgroud)

鉴于这些类型声明,C#规范的哪一部分解释了为什么以下代码片段的最后一行打印"True"?开发人员可以依赖这种行为吗?

Derived d = new Derived();
Base b = d;
ICloneable<Base> cb = d;
Console.WriteLine(b.Clone() is Derived); // "False": Base.Clone() is called
Console.WriteLine(cb.Clone() is Derived); // "True": Derived.Clone() is called
Run Code Online (Sandbox Code Playgroud)

需要注意的是,如果T在类型参数ICloneable没有声明out,则这两条线将打印"假".

c# covariance contravariance variance c#-4.0

20
推荐指数
1
解决办法
454
查看次数

在Stream.reduce()这样的API中选择不变性有什么好理由?

回顾Java 8 StreamAPI设计,我对Stream.reduce()参数的泛型不变性感到惊讶:

<U> U reduce(U identity,
             BiFunction<U,? super T,U> accumulator,
             BinaryOperator<U> combiner)
Run Code Online (Sandbox Code Playgroud)

相同API的看似更通用的版本可能在个别引用上应用了协方差/逆变U,例如:

<U> U reduce(U identity,
             BiFunction<? super U, ? super T, ? extends U> accumulator,
             BiFunction<? super U, ? super U, ? extends U> combiner)
Run Code Online (Sandbox Code Playgroud)

这将允许以下目前无法实现的目标:

// Assuming we want to reuse these tools all over the place:
BiFunction<Number, Number, Double> numberAdder =
    (t, u) -> t.doubleValue() + u.doubleValue();

// This currently doesn't work, but would work with the suggestion
Stream<Number> stream …
Run Code Online (Sandbox Code Playgroud)

java covariance contravariance java-stream invariance

20
推荐指数
1
解决办法
454
查看次数