C# .Net 3.5 使用具有不同返回类型的重载索引器
我有一个父类,它本质上是一个美化的列表。它由多个子类扩展以实现各种功能。
public class HierarchialItemList<ItemType> : IEnumerable<ItemType>
{
public ItemType this[String itemCode]
{
get
{
foreach (IHierarchialItem curItem in hierarchialItems)
{
if (curItem.Code.Equals(itemCode, StringComparison.CurrentCultureIgnoreCase))
{
return ((ItemType)curItem);
}
}
return (default(ItemType));
}
}
public ItemType this[Int32 index]
{
get
{
return (hierarchialItems[index]);
}
}
}
public class DatabaseList : HierarchialItemList<Database>
{
public DatabaseList this[CommonDatabaseType typeToFilter]
{
get
{
DatabaseList returnList = new DatabaseList();
foreach(Database curDatabase in this)
{
if (curDatabase.DatabaseType.Equals(typeToFilter))
{
returnList.Add(curDatabase);
}
}
return (returnList);
}
}
public DatabaseList this[Environments.RMSEnvironment environmentToFilter]
{
get
{
DatabaseList returnList = new DatabaseList();
foreach(Database curDatabase in this)
{
if (curDatabase.ParentEnvironment.Equals(environmentToFilter))
{
returnList.Add(curDatabase);
}
}
return (returnList);
}
}
}
问题在于 C# 认为:
Database testDatabase = sampleDatabaseList[0];
是一个错误,并且索引器应该返回 DatabaseList,而不是数据库。你我都知道那是假的。有什么解决方法吗?或者所有索引器都必须具有相同的返回类型吗?
编辑:我刚刚发现这是因为使用枚举作为索引器,它内部是一个整数。不过,有什么方法可以同时使用枚举和整数吗?
编辑2:根据要求,这里有一些可编译的测试代码,它演示了该问题。
using System;
using System.Collections.Generic;
namespace CSQT
{
class A<T>
{
List<T> temp;
public A()
{
temp = new List<T>();
}
public void AddItem(T itemToAdd)
{
temp.Add(itemToAdd);
}
public T this[String code]
{
get { return (temp[0]); }
}
public T this[Int32 index]
{
get { return (temp[index]); }
}
}
class B : A<String>
{
public B()
: base()
{
}
public B this[BTypes testType]
{
get
{
return (this);
}
}
}
enum BTypes { TEMP1, TEMP2 };
class C
{
public C()
{
B temp = new B();
//Compile error: Cannot implicitly convert type 'CSQT.B' to 'string'
String temp2 = temp[0];
//Compile error: Cannot convert type 'CSQT.B' to 'string'
String temp3 = (String)temp[0];
//This compiles and runs but instead of going to A.this[int32], it goes to B.this[BTypes testType]
B temp4 = temp[0];
}
}
}
I have a parent class which is essentially a glorified list. It's extended by several subclasses for various functionalities.
public class HierarchialItemList<ItemType> : IEnumerable<ItemType>
{
public ItemType this[String itemCode]
{
get
{
foreach (IHierarchialItem curItem in hierarchialItems)
{
if (curItem.Code.Equals(itemCode, StringComparison.CurrentCultureIgnoreCase))
{
return ((ItemType)curItem);
}
}
return (default(ItemType));
}
}
public ItemType this[Int32 index]
{
get
{
return (hierarchialItems[index]);
}
}
}
public class DatabaseList : HierarchialItemList<Database>
{
public DatabaseList this[CommonDatabaseType typeToFilter]
{
get
{
DatabaseList returnList = new DatabaseList();
foreach(Database curDatabase in this)
{
if (curDatabase.DatabaseType.Equals(typeToFilter))
{
returnList.Add(curDatabase);
}
}
return (returnList);
}
}
public DatabaseList this[Environments.RMSEnvironment environmentToFilter]
{
get
{
DatabaseList returnList = new DatabaseList();
foreach(Database curDatabase in this)
{
if (curDatabase.ParentEnvironment.Equals(environmentToFilter))
{
returnList.Add(curDatabase);
}
}
return (returnList);
}
}
}
The problem is that C# thinks that this:
Database testDatabase = sampleDatabaseList[0];
Is an error and that the indexer should be returning a DatabaseList, not a Database. You and I both know that's false. Any workarounds or do all indexers have to have the same return type?
Edit: I just figured out that it's because of using an enumeration as an indexer which is internally an integer. Still, any way to use both an enumeration and an integer?
Edit 2: As requested, here is some compiliable test code which demonstrates the problem.
using System;
using System.Collections.Generic;
namespace CSQT
{
class A<T>
{
List<T> temp;
public A()
{
temp = new List<T>();
}
public void AddItem(T itemToAdd)
{
temp.Add(itemToAdd);
}
public T this[String code]
{
get { return (temp[0]); }
}
public T this[Int32 index]
{
get { return (temp[index]); }
}
}
class B : A<String>
{
public B()
: base()
{
}
public B this[BTypes testType]
{
get
{
return (this);
}
}
}
enum BTypes { TEMP1, TEMP2 };
class C
{
public C()
{
B temp = new B();
//Compile error: Cannot implicitly convert type 'CSQT.B' to 'string'
String temp2 = temp[0];
//Compile error: Cannot convert type 'CSQT.B' to 'string'
String temp3 = (String)temp[0];
//This compiles and runs but instead of going to A.this[int32], it goes to B.this[BTypes testType]
B temp4 = temp[0];
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
为什么我们知道这是假的?该行
使用参数
0
调用索引器,该参数是int
文字,因此,看到DatabaseList
继承自HierarchialItemList;
将调用定义的索引器,该索引器声明返回
ItemType
。您还没有告诉我们ItemType
是什么。我们没有理由知道ItemType
可以分配给Database
类型的变量。索引器不必返回相同的类型。但是,不可能仅根据返回类型进行重载。也就是说,这是合法的
这不是
对您的编辑的回应:
如果您想调用接受枚举的索引器,请像这样调用它:
Why do we know that to be false? The line
invokes the indexer with the parameter
0
which is aint
literal and therefore, seeing thatDatabaseList
inherits fromHierarchialItemList<Database>
will invoke the indexer defined bywhich is declared to return an
ItemType
. You haven't told us whatItemType
is. We have no reason to know that anItemType
can be assigned to a variable of typeDatabase
.Indexers do not have to return the same type. However, it is not possible to overload solely on the basis of return type. That is, this is legal
This is not
Responding to your edit:
If you want to invoke the indexer that accepts an enum, invoke it like so:
这是完全有效的代码。
This is perfectly valid code.
添加必要的类和属性来编译代码示例后,我可以毫无问题地运行此语句:
Database testDatabase = sampleDatabaseList[0];
如果您收到以下错误:< code>sampleDatabaseList[0] 返回 DatabaseList,请提供包含语句
DatabaseList testDatabase = sampleDatabaseList[0];
的可编译代码示例After adding the necessary classes and attributes to get your code sample to compile, I was able to run this statement with no issues:
Database testDatabase = sampleDatabaseList[0];
If you're getting an error that
sampleDatabaseList[0]
returns a DatabaseList, please provide a compilable code sample that contains the statementDatabaseList testDatabase = sampleDatabaseList[0];