请看以下示例(部分取自MSDN博客):
class Animal { }
class Giraffe : Animal { }
static void Main(string[] args)
{
// Array assignment works, but...
Animal[] animals = new Giraffe[10];
// implicit...
List<Animal> animalsList = new List<Giraffe>();
// ...and explicit casting fails
List<Animal> animalsList2 = (List<Animal>) new List<Giraffe>();
}
Run Code Online (Sandbox Code Playgroud)
这是一个协方差问题吗?这将在未来的C#版本中得到支持吗?是否有任何聪明的解决方法(仅使用.NET 2.0)?
是否有可能投下List<Subclass>到List<Superclass>在C#4.0?
这些方面的东西:
class joe : human {}
List<joe> joes = GetJoes();
List<human> humanJoes = joes;
Run Code Online (Sandbox Code Playgroud)
这不是协方差的意思吗?
如果你能做到:
human h = joe1 as human;
Run Code Online (Sandbox Code Playgroud)
你为什么不能这样做
List<human> humans = joes as List<human>;
Run Code Online (Sandbox Code Playgroud)
因为那个项目已经被贬低了,所以做人类[0]是不合法的,每个人都会很高兴.现在唯一的选择是创建一个新的List
为什么C#编译器不允许泛型集合中的多态类型(T)参数(即List [T])?
以"A"和"B"为例,其中"B"是"A"的子类
class A { }
class B : A { }
Run Code Online (Sandbox Code Playgroud)
并考虑一个带有'A'类型列表的函数
void f(List<A> aL) { }
Run Code Online (Sandbox Code Playgroud)
用"B"类型的列表调用
List<B> bL = new List<B>();
f(bL);
Run Code Online (Sandbox Code Playgroud)
给出以下错误
ERROR: cannot convert from List<B> to List<A>
Run Code Online (Sandbox Code Playgroud)
违反了什么语义规则?
除此之外,还有一个"优雅"的意思,除了循环和铸造每个元素(我想要一些糖)?谢谢.
我有一个基础WPF UserControl,它处理派生UserControls的一些常用功能.在任何派生的UserControl的代码隐藏中,我调用一个事件
private void SomeClick(object sender, RoutedEventArgs e) {
HandleClick(sender);
MyDataGrid.Items.Refresh();
}
Run Code Online (Sandbox Code Playgroud)
在我的基础UserControl我做
public class BaseUserControl : UserControl {
protected void HandleClick(object sender) {
var vm = (BaseViewModel<Part>)DataContext;
...
}
}
Run Code Online (Sandbox Code Playgroud)
这会引发InvalidCastException,因为DataContext它是类型BaseViewModel但派生类型如BaseViewModel<Wire>或BaseViewModel<Connector>.
我怎么能这样做?
以下为什么不工作?
List<string> castMe = new List<string>();
IEnumerable<string> getFromCast = (IEnumerable<string>)castMe; // allowed.
Dictionary<int, List<string>> castMeDict = new Dictionary<int, List<string>>();
Dictionary<int, IEnumerable<string>> getFromDict = (Dictionary<int, IEnumerable<string>>)castMeDict; // Not allowed
Run Code Online (Sandbox Code Playgroud)
这是Dictionary铸造机制中的一个缺陷,还是我认为应该允许这样做?
谢谢.
我的理解是,如果S是一个子类的T,那么List<S>是不是一个孩子List<T>.精细.但是接口有不同的范例:如果是Foo实现IFoo,那么为什么List<Foo>不是(一个例子)List<IFoo>?
因为可能没有实际的类IFoo,这是否意味着我在暴露a时总是必须强制转换列表中的每个元素List<IFoo>?或者这只是糟糕的设计,我必须定义自己的集合类ListOfIFoos才能与它们一起工作?对我来说似乎都不合理......
考虑到我正在尝试编程接口,那么暴露这样一个列表的最佳方式是什么?我目前正倾向于实际存储我的List<Foo>内部作为List<IFoo>.
最近我在c#中发现了一个非常令人惊讶的行为.我有一个方法,它IEnumerable<Object>作为参数,我正在通过,
IEnumerable<string>但它是不可能的.虽然在c#中,所有内容都可以向上转换为对象而不是为什么这是不可能的?这让我很困惑.请有人在这个问题上告诉我.
它经常听说Haskell(我不知道)有一个非常有趣的类型系统.我对Java非常熟悉,而且对C#有点熟悉,有时我会对类型系统进行战斗,所以有些设计适应或以某种方式更好地工作.
这让我想知道......
由于Java/C#类型系统的不足,以某种方式出现了什么问题?你是如何处理它们的?
我在VB.net工作并有一个Class,Foo,它实现了一个接口,IBar.我有一个Foo列表,但我需要将一个IBar列表传递给一个函数,但即使我使用DirectCast,我仍然会出现转换错误.我的代码是
Class Foo
Implements IBar
End Class
Interface IBar
End Interface
Sub DoIt(ByVal l As List(Of IBar))
End Sub
Sub Main()
Dim FooList As New List(Of Foo)
DoIt(FooList)
End Sub
Sub Main2()
Dim FooList As New List(Of Foo)
DoIt(DirectCast(FooList, List(Of IBar)))
End Sub
Sub MainWorks()
Dim FooList As New List(Of Foo)
Dim IBarList As New List(Of IBar)
For Each f As Foo In FooList
IBarList.Add(f)
Next
DoIt(DirectCast(IBarList, List(Of IBar)))
DoIt(IBarList)
End Sub
Run Code Online (Sandbox Code Playgroud)
在主要和主要2我得到
Value of type 'System.Collections.Generic.List(Of FreezePod.Pod.Foo)' cannot be …Run Code Online (Sandbox Code Playgroud) 我今天碰到了编辑问题,这让我感到困惑.考虑这两个容器类.
public class BaseContainer<T> : IEnumerable<T>
{
public void DoStuff(T item) { throw new NotImplementedException(); }
public IEnumerator<T> GetEnumerator() { }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { }
}
public class Container<T> : BaseContainer<T>
{
public void DoStuff(IEnumerable<T> collection) { }
public void DoStuff <Tother>(IEnumerable<Tother> collection)
where Tother: T
{
}
}
Run Code Online (Sandbox Code Playgroud)
前者定义DoStuff(T item),后者DoStuff <Tother>(IEnumerable<Tother>)专门用它来解决C#的协方差/逆变的缺失(直到4听到).
这段代码
Container<string> c = new Container<string>();
c.DoStuff("Hello World");
Run Code Online (Sandbox Code Playgroud)
遇到一个相当奇怪的编译错误.请注意<char>方法调用中没有.
类型'char'不能用作泛型类型或方法'Container.DoStuff(System.Collections.Generic.IEnumerable)'中的类型参数'Tother'.从'char'到'string'没有拳击转换.
从本质上讲,编译器试图我的电话果酱DoStuff(string)进入Container.DoStuff<char>(IEnumerable<char>),因为string工具IEnumerable<char>,而不是使用BaseContainer.DoStuff(string) …
c# ×9
covariance ×5
generics ×4
casting ×3
.net ×1
compilation ×1
dictionary ×1
haskell ×1
interface ×1
java ×1
oop ×1
type-systems ×1
vb.net ×1
wpf ×1