开发者

C# .Net 3.5 Using Overloaded Indexers with different return types

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]); }

    }
}

cla开发者_Python百科ss 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];
    }
}
}


Why do we know that to be false? The line

Database testDatabase = sampleDatabaseList[0];

invokes the indexer with the parameter 0 which is a int literal and therefore, seeing that DatabaseList inherits from HierarchialItemList<Database> will invoke the indexer defined by

public ItemType this[Int32 itemCode] { get; }

which is declared to return an ItemType. You haven't told us what ItemType is. We have no reason to know that an ItemType can be assigned to a variable of type Database.

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

class IndexerTest {
    public int this[int index] {
        get {
            return 0;
        }
    }

    public string this[double index] {
        get {
            return "Hello, success!";
        }
    }
}

This is not

class IndexerTest {
    public int this[int index] {
        get {
            return 0;
        }
    }

    public string this[int index] {
        get {
            return "Hello, fail!";
        }
    }
}

Responding to your edit:

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?

If you want to invoke the indexer that accepts an enum, invoke it like so:

sampleDatabaseList[Environments.RMSEnvironment.SomeEnumValue];


This is perfectly valid code.

class SomeClass { }
public class A<T> : IEnumerable<T>
{

    public T this[int index]
    {
        get
        {
            return (this[index]);
        }
    }

    public T this[String index]
    {
        get
        {
            return (this[index]);
        }
    }

}
public class B : A<SomeClass>
{
    public B this[char typeToFilter]
    {
        get
        {
            return new B();
        }
    }
}


        B classList = new B();
        SomeClass test = classList[0];


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestNameSpace
{
    public class Employee : Person
    {
        string id;
        public string Id
        {
            get { return id; }
            set { id = value; }
        }

        decimal salary;
        public decimal Salary
        {
            get { return salary; }
            set { salary = value; }
        }

        string password;
        public string Password
        {
            set { password = value; }
        }

        int ichk = 1, schk = 1, pchk = 1;


        public Employee()
            : base()
        {
            Id = null;
            Salary = Convert.ToDecimal("0.0");
            Password = null;
        }

        public Employee(string n, char g, DateTime d, string empid, decimal sal, string pwd)
            : base(n, g, d)
        {
            Id = empid;
            Salary = sal;
            Password = pwd;
        }

        public override void Accept()
        {
            base.Accept();
            try
            {
                Console.Write("Enter the EMPID:");
                Id = Console.ReadLine();
                if (string.IsNullOrEmpty(Id) == true)
                {
                    ichk = 0;
                    Console.WriteLine("No ID entered!");
                }

                string salcheck;
                Console.Write("Enter the Salary:");
                salcheck = Console.ReadLine();
                if (string.IsNullOrEmpty(salcheck) == true)
                {
                    schk = 0;
                    Console.WriteLine("Invalid Salary");
                }
                else
                {
                    Salary = Convert.ToDecimal(salcheck);
                    if (Salary < 0)
                    {
                        schk = 0;
                        Console.WriteLine("Invalid Salary");
                    }
                }

                Console.Write("Enter Password:");
                Password = Console.ReadLine();
                if (string.IsNullOrEmpty(password) == true)
                {
                    pchk = 0;
                    Console.WriteLine("Empty Password!");
                }
                else
                {
                    string pwd;
                    int pchk = 0;
                    do
                    {
                        Console.Write("Re-Enter Password:");
                        pwd = Console.ReadLine();
                        if (string.IsNullOrEmpty(pwd) == true || pwd != password)
                            Console.WriteLine("Passwords don't match!");
                        else
                            pchk = 1;
                    } while (pchk == 0);
                }
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
            }

        }


        public override void Print()
        {
            base.Print();

            if (ichk == 1)
            {
                Console.WriteLine("EMPID:{0}", Id);
            }
            else
                Console.WriteLine("No Id!");

            if (schk == 1)
            {
                Console.WriteLine("Salary:{0}", Salary);
            }
            else
                Console.WriteLine("Invalid Salary!");

        }

    }
}

------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestNameSpace
{
    public class Person
    {
        protected string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        protected char gender;
        public char Gender
        {
            get { return gender; }
            set { gender = value; }
        }

        protected DateTime? dob;
        public DateTime? Dob
        {
            get { return dob; }
            set { dob = value; }
        }

        protected int age;
        public int Age
        {
            get { return age; }
        }

        public Person()
        {
            Name = "Default";
            Gender = 'M';
            Dob = null;
            age = 0;
        }
        public Person(string n, char g, DateTime d)
        {
            Name = n;
            Gender = g;
            Dob = d;
            age = DateTime.Now.Year - Dob.Value.Year;
        }

        int nchk = 1, gchk = 0, dchk = 0;
        string datetimecheck, gendercheck;
        public virtual void Accept()
        {
            try
            {
                Console.Write("Enter the name:");
                Name = Console.ReadLine();
                if (string.IsNullOrEmpty(Name)==true)
                {
                    nchk = 0;
                    Console.WriteLine("No name entered!");
                }

                Console.Write("Enter the Date of birth:");
                datetimecheck = Console.ReadLine();
                if (string.IsNullOrEmpty(datetimecheck) == true)
                {                    
                    dchk = 0;
                    Console.WriteLine("No date entered!");
                }
                else
                {
                    Dob = Convert.ToDateTime(datetimecheck);
                    age = DateTime.Now.Year - Dob.Value.Year;
                    dchk = 1;
                }

                Console.Write("Enter Gender:");
                gendercheck = Console.ReadLine();
                if (gendercheck != "m" && gendercheck != "M" && gendercheck != "f" && gendercheck != "F")
                {
                    gchk = 0;
                    Console.WriteLine("Invalid Gender");
                }
                else
                {
                    gchk = 1;
                    Gender = Convert.ToChar(gendercheck);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

        }

        public virtual void Print()
        {
            Console.WriteLine("\n\nThe Employee Details are:\n");

            if (nchk == 1)
            {
                Console.WriteLine("Name:{0}", Name);
            }
            else
                Console.WriteLine("No Name!");

            if (gchk == 1)
            {
                Console.WriteLine("Gender:{0}", Gender);
            }
            else
                Console.WriteLine("No Gender!");

            if (dchk == 1)
            {
                Console.WriteLine("Date Of Birth:{0}", Dob);
                Console.WriteLine("Age:{0}", Age);
            }
            else
                Console.WriteLine("No Date Of Birth!");
        }
    }
}


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 statement DatabaseList testDatabase = sampleDatabaseList[0];


---TRIGGER--

CREATE TRIGGER TriggerTest
ON EMP
AFTER INSERT, UPDATE, DELETE 

AS
BEGIN

declare @day varchar(10)
select @day=datename(dw,getdate())

declare @hour int
Select @hour=convert(varchar(2),getdate(),114)

if ( @hour < 9 OR @hour > 13 OR @day = 'Saturday' OR @day = 'Sunday')
BEGIN

if UPDATE(EMPID)
RAISERROR ('Error!',1,16)
rollback tran

END

END

Insert into EMP values(1003,'A','A')

drop trigger TriggerTest
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestNameSpace
{
    public class Employee:Person
    {
        string id;
        public string Id
        {
            get { return id; }
            set { id = value; }
        }

        decimal salary;
        public decimal Salary
        {
            get { return salary; }
            set { salary = value; }
        }

        string password;
        public string Password
        {
            set { password = value; }
        }

        int ichk = 1, schk = 1, pchk = 1;


        public Employee()
            : base()
        {
            Id = null;
            Salary = Convert.ToDecimal("0.0");
            Password = null;
        }

        public Employee(string n, char g, DateTime d, string empid, decimal sal, string pwd)
            : base(n, g, d)
        {
            Id = empid;
            Salary = sal;
            Password = pwd;
        }

        public override void Accept()
        {
            base.Accept();
            try
            {
                Console.Write("Enter the EMPID:");
                Id = Console.ReadLine();
                if (Id == null)
                {
                    ichk = 0;
                    Console.WriteLine("No ID entered!");
                }

                Console.Write("Enter the Salary:");
                Salary = Convert.ToDecimal(Console.ReadLine());
                if (Salary < 0)
                {
                    schk = 0;
                    Console.WriteLine("Invalid Salary");
                }

                Console.Write("Enter Password:");
                Password = Convert.ToString(Console.ReadLine());
                if (password == null)
                {
                    pchk = 0;
                    Console.WriteLine("Empty Password!");
                }
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
            }

        }


        public override void Print()
        {
            base.Print(); 

            if (ichk == 1)
            {
                Console.WriteLine("EMPID:{0}", Id);
            }
            else
                Console.WriteLine("No Id!");

            if (schk == 1)
            {
                Console.WriteLine("Salary:{0}", Salary);
            }
            else
                Console.WriteLine("Invalid Salary!");

        }

    }
}



-----PERSON-----
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestNameSpace
{
    public class Person
    {
        protected string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        protected char gender;
        public char Gender
        {
            get { return gender; }
            set { gender = value; }
        }

        protected DateTime dob;
        public DateTime Dob
        {
            get { return dob; }
            set { dob = value; }
        }

        protected int age;
        public int Age
        {
            get { return age; }            
        }

        public Person()
        {
            Name = "Default";
            Gender = 'M';
            Dob = Convert.ToDateTime("09 / 12 / 1990");
            age = 0;
        }
        public Person(string n, char g, DateTime d)
        {
            Name = n;
            Gender = g;
            Dob = d;
            age = DateTime.Now.Year - Dob.Year;
        }

        int nchk = 1, gchk = 1, dchk = 1;
        public virtual void Accept()
        {
            try
            {
                Console.Write("Enter the name:");
                Name = Console.ReadLine();
                if(Name == null)
                {
                    nchk = 0;
                    Console.WriteLine("No name entered!");
                }

                Console.Write("Enter the Date of birth:");
                Dob = Convert.ToDateTime(Console.ReadLine());
                if (Dob == null)
                {
                    dchk = 0;
                    Console.WriteLine("No date entered!");
                }
                else
                {
                    age = DateTime.Now.Year - Dob.Year;
                }

                Console.Write("Enter Gender:");
                Gender = Convert.ToChar(Console.ReadLine());
                if (Gender != 'm' && Gender != 'M' && Gender != 'F' && Gender != 'f')
                {
                    gchk = 0;
                    Console.WriteLine("Invalid Gender");                   
                }
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
            }

        }

        public virtual void Print()
        {
            Console.WriteLine("\n\nThe Employee Details are:\n");

            if (nchk == 1)
            {
                Console.WriteLine("Name:{0}", Name);
            }
            else
                Console.WriteLine("No Name!");

            if (gchk == 1)
            {
                Console.WriteLine("Gender:{0}", Gender);
            }
            else
                Console.WriteLine("No Gender!");

            if (dchk == 1)
            {
                Console.WriteLine("Date Of Birth:{0}", Dob);
                Console.WriteLine("Age:{0}", Age);
            }
            else
                Console.WriteLine("No Date Of Birth!");
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜