This works from C#, but not C++ / CLI

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Howard Swope

    This works from C#, but not C++ / CLI

    This problem has been bugging me for a while. I have created a collection
    class and implemented it in a C# library. If I inherit from this class in
    another C# assembly and it works, but if I inherit from this class in a C++
    / CLI assembly it won't compile.

    This indicates a problem in the CLR. Can anyone shed some light on this. The
    class follows:

    public abstract class DictionaryBase< TKey,TValue:
    IDictionary<TKe y,TValue>,
    ICollection<Key ValuePair<TKey, TValue>>,
    IEnumerable<Key ValuePair<TKey, TValue>>,
    IDictionary,
    ICollection,
    IEnumerable,
    ISerializable,
    IDeserializatio nCallback
    {
    protected Dictionary<TKey , TValuedictionar y;

    #region Constructors
    public DictionaryBase( )
    {
    dictionary = new Dictionary<TKey , TValue>();
    }

    public DictionaryBase( IDictionary<TKe y,TValuediction ary)
    {
    this.dictionary = new Dictionary<TKey ,
    TValue>(diction ary);
    }

    public DictionaryBase( IEqualityCompar er<TKeycomparer )
    {
    dictionary = new Dictionary<TKey , TValue>(compare r);
    }

    public DictionaryBase( int capacity)
    {
    dictionary = new Dictionary<TKey , TValue>(capacit y);
    }

    public DictionaryBase( IDictionary<TKe y, TValuedictionar y,
    IEqualityCompar er<TKeycomparer )
    {
    dictionary = new Dictionary<TKey , TValue>(diction ary,
    comparer);
    }

    public DictionaryBase( int capacity, IEqualityCompar er<TKey>
    comparer)
    {
    dictionary = new Dictionary<TKey , TValue>(capacit y,
    comparer);
    }

    #endregion

    #region Properties
    public virtual IEqualityCompar er<TKeyComparer
    {
    get { return dictionary.Comp arer; }
    }

    public virtual int Count
    {
    get { return dictionary.Coun t; }
    }

    public virtual TValue this[TKey key]
    {
    get { return dictionary[key]; }
    set { dictionary[key] = value; }
    }

    public virtual Dictionary<TKey ,TValue>.KeyCol lection Keys
    {
    get { return dictionary.Keys ; }
    }

    public virtual Dictionary<TKey , TValue>.ValueCo llection Values
    {
    get { return dictionary.Valu es;}
    }

    public virtual bool IsReadOnly
    {
    get { return false; }
    }

    public virtual bool IsFixedSize
    {
    get { return false; }
    }

    public virtual bool IsSynchronized
    {
    get { return false; }
    }

    public virtual object SyncRoot
    {
    get { return null; }
    }
    #endregion

    #region Methods
    public virtual void Add(TKey key, TValue value)
    {
    dictionary.Add( key, value);
    }

    public virtual void Clear()
    {
    dictionary.Clea r();
    }

    public virtual bool ContainsKey(TKe y key)
    {
    return dictionary.Cont ainsKey(key);
    }

    public virtual bool ContainsValue(T Value value)
    {
    return dictionary.Cont ainsValue(value );
    }

    public virtual bool Contains(KeyVal uePair<TKey,TVa lueitem)
    {
    if (dictionary.Con tainsKey(item.K ey) &&
    dictionary[item.Key].Equals(item.Va lue))
    return true;
    else
    return false;
    }

    public override bool Equals(Object obj)
    {
    return dictionary.Equa ls(obj);
    }

    public virtual Dictionary<TKey ,TValue>.Enumer ator
    GetEnumerator()
    {
    return dictionary.GetE numerator();
    }

    public override int GetHashCode()
    {
    return dictionary.GetH ashCode();
    }

    public virtual void GetObjectData(S erializationInf o info,
    StreamingContex t context)
    {
    dictionary.GetO bjectData(info, context);
    }

    public virtual void OnDeserializati on(Object sender)
    {
    dictionary.OnDe serialization(s ender);
    }

    public virtual bool Remove(TKey key)
    {
    return dictionary.Remo ve(key);
    }

    public virtual bool Remove(KeyValue Pair<TKey,TValu eitem)
    {
    if (dictionary.Con tainsKey(item.K ey) &&
    dictionary[item.Key].Equals(item.Va lue))
    {
    dictionary.Remo ve(item.Key);
    return true;
    }
    else
    {
    return false;
    }
    }

    public override String ToString()
    {
    return dictionary.ToSt ring();
    }

    public virtual bool TryGetValue(TKe y key, out TValue value)
    {
    if (dictionary.Con tainsKey(key))
    {
    value = this[key];
    return true;
    }
    else
    {
    value = default(TValue) ;
    return false;
    }
    }

    public virtual void CopyTo(KeyValue Pair<TKey,TValu e>[] array,
    int arrayIndex)
    {
    int count = 0;
    foreach (KeyValuePair<T Key,TValueitem in dictionary)
    {
    array[arrayIndex + count] =
    new
    KeyValuePair<TK ey,TValue>(item .Key,item.Value );
    ++count;
    }
    }

    #endregion

    #region IDictionary<TKe y,TValueMembers

    void IDictionary<TKe y, TValue>.Add(TKe y key, TValue value)
    {
    this.Add(key,va lue);
    }

    bool IDictionary<TKe y, TValue>.Contain sKey(TKey key)
    {
    return this.ContainsKe y(key);
    }

    ICollection<TKe yIDictionary<TK ey, TValue>.Keys
    {
    get { return this.Keys; }
    }

    bool IDictionary<TKe y, TValue>.Remove( TKey key)
    {
    return this.Remove(key );
    }

    ICollection<TVa lueIDictionary< TKey, TValue>.Values
    {
    get { return this.Values; }
    }

    TValue IDictionary<TKe y, TValue>.this[TKey key]
    {
    get
    {
    return this[key];
    }
    set
    {
    this[key] = value;
    }
    }

    #endregion

    #region ICollection<Key ValuePair<TKey, TValue>Members

    void ICollection<Key ValuePair<TKey,
    TValue>>.Add(Ke yValuePair<TKey , TValueitem)
    {
    this.Add(item.K ey,item.Value);
    }

    void ICollection<Key ValuePair<TKey, TValue>>.Clear( )
    {
    this.Clear();
    }

    bool ICollection<Key ValuePair<TKey,
    TValue>>.Contai ns(KeyValuePair <TKey, TValueitem)
    {
    return this.Contains(i tem);
    }

    void ICollection<Key ValuePair<TKey,
    TValue>>.CopyTo (KeyValuePair<T Key, TValue>[] array, int arrayIndex)
    {
    this.CopyTo(arr ay,arrayIndex);
    }

    int ICollection<Key ValuePair<TKey, TValue>>.Count
    {
    get { return this.Count; }
    }

    bool ICollection<Key ValuePair<TKey, TValue>>.IsRead Only
    {
    get { return this.IsReadOnly ; }
    }

    bool ICollection<Key ValuePair<TKey,
    TValue>>.Remove (KeyValuePair<T Key, TValueitem)
    {
    return this.Remove(ite m);
    }

    #endregion

    #region IEnumerable<Key ValuePair<TKey, TValue>Members

    IEnumerator<Key ValuePair<TKey, TValue>>
    IEnumerable<Key ValuePair<TKey, TValue>>.GetEnu merator()
    {
    return this.GetEnumera tor();
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.Get Enumerator()
    {
    return this.GetEnumera tor();
    }

    #endregion

    #region IDictionary Members

    void IDictionary.Add (object key, object value)
    {
    this.Add((TKey) key,(TValue)val ue);
    }

    void IDictionary.Cle ar()
    {
    this.Clear();
    }

    bool IDictionary.Con tains(object key)
    {
    return this.ContainsKe y((TKey)key);
    }

    IDictionaryEnum erator IDictionary.Get Enumerator()
    {
    return this.GetEnumera tor();
    }

    bool IDictionary.IsF ixedSize
    {
    get { return this.IsFixedSiz e; }
    }

    bool IDictionary.IsR eadOnly
    {
    get { return this.IsReadOnly ; }
    }

    ICollection IDictionary.Key s
    {
    get { return this.Keys; }
    }

    void IDictionary.Rem ove(object key)
    {
    this.Remove((TK ey)key);
    }

    ICollection IDictionary.Val ues
    {
    get { return this.Values; }
    }

    object IDictionary.thi s[object key]
    {
    get
    {
    return this[(TKey)key];
    }
    set
    {
    this[(TKey)key] = (TValue)value;
    }
    }

    #endregion

    #region ICollection Members

    void ICollection.Cop yTo(Array array, int index)
    {
    this.CopyTo((Ke yValuePair<TKey ,TValue>[])array,index);
    }

    int ICollection.Cou nt
    {
    get { return this.Count; }
    }

    bool ICollection.IsS ynchronized
    {
    get { return this.IsSynchron ized; }
    }

    object ICollection.Syn cRoot
    {
    get { return this.SyncRoot; }
    }

    #endregion

    #region ISerializable Members

    void ISerializable.G etObjectData(Se rializationInfo info,
    StreamingContex t context)
    {
    this.GetObjectD ata(info,contex t);
    }

    #endregion

    #region IDeserializatio nCallback Members

    void IDeserializatio nCallback.OnDes erialization(ob ject sender)
    {
    this.OnDeserial ization(sender) ;
    }

    #endregion
    }


    --
    Howard Swope [ mailto:howard.s wopeATnavteqDOT com ]
    Technical Lead
    Media Development
    Navteq Traffic [ http://www.navteq.com ] [ http://www.traffic.com ]


  • Jon Skeet [C# MVP]

    #2
    Re: This works from C#, but not C++ / CLI

    <"Howard Swope" <howard.swopeAT navteqDOTcom>wr ote:
    This problem has been bugging me for a while. I have created a collection
    class and implemented it in a C# library. If I inherit from this class in
    another C# assembly and it works, but if I inherit from this class in a C++
    / CLI assembly it won't compile.
    Could you give more details than "it won't compile"? The error message
    would be a good start - some sample (failing) code would be better. The
    absolute ideal would be to cut down on the amount of code in your
    collection class as well, until you've got a minimal failure.
    This indicates a problem in the CLR.
    Why? I'd have thought it would be a problem with the C++/CLI compiler
    if anything.

    --
    Jon Skeet - <skeet@pobox.co m>
    Web site: http://www.pobox.com/~skeet
    Blog: http://www.msmvps.com/jon.skeet
    C# in Depth: http://csharpindepth.com

    Comment

    • Pavel Minaev

      #3
      Re: This works from C#, but not C++ / CLI

      Howard Swope wrote:
      This problem has been bugging me for a while. I have created a collection
      class and implemented it in a C# library. If I inherit from this class in
      another C# assembly and it works, but if I inherit from this class in a C++
      / CLI assembly it won't compile.
      >
      This indicates a problem in the CLR. Can anyone shed some light on this. The
      class follows:
      [... snip ...]
      I did not have any trouble compiling this:

      ref class MyDictionary : public DictionaryBase< int, System::String^ >
      {
      };

      If you could post your C++/CLI code here, and the error message you
      get, we could probably tell you more (though it would be somewhat
      offtopic in a C# group, I guess).

      One thing though - are you sure you did not forget "ref" in your C++/
      CLI class declaration?

      Comment

      • Howard Swope

        #4
        Re: This works from C#, but not C++ / CLI

        The errors I am getting when I try to inherit from this class with

        public ref class MyDictionary : DictionaryBase< String^, Object^>

        {

        public:

        MyDictionary(vo id);

        };



        are


        Error 1 error C3766: 'MyDictionary' must provide an implementation for the
        interface method 'System::Collec tions::Generic: :IEnumerator<T>
        ^System::Collec tions::Generic: :IEnumerable<T> ::GetEnumerator (void)'

        Error 2 error C3766: 'MyDictionary' must provide an implementation for the
        interface method 'void
        System::Collect ions::Generic:: ICollection<T>: :Add(System::Co llections::Gene ric::KeyValuePa ir<TKey,TValue> )'

        Error 3 error C3766: 'MyDictionary' must provide an implementation for the
        interface method 'System::Collec tions::Generic: :ICollection<T>
        ^System::Collec tions::Generic: :IDictionary<TK ey,TValue>::Key s::get(void)'

        Error 4 error C3766: 'MyDictionary' must provide an implementation for the
        interface method 'System::Collec tions::Generic: :ICollection<T>
        ^System::Collec tions::Generic: :IDictionary<TK ey,TValue>::Val ues::get(void)'


        "Jon Skeet [C# MVP]" <skeet@pobox.co mwrote in message
        news:MPG.22f989 2f155f845e79@ms news.microsoft. com...
        <"Howard Swope" <howard.swopeAT navteqDOTcom>wr ote:
        >This problem has been bugging me for a while. I have created a collection
        >class and implemented it in a C# library. If I inherit from this class in
        >another C# assembly and it works, but if I inherit from this class in a
        >C++
        >/ CLI assembly it won't compile.
        >
        Could you give more details than "it won't compile"? The error message
        would be a good start - some sample (failing) code would be better. The
        absolute ideal would be to cut down on the amount of code in your
        collection class as well, until you've got a minimal failure.
        >
        >This indicates a problem in the CLR.
        >
        Why? I'd have thought it would be a problem with the C++/CLI compiler
        if anything.
        >
        --
        Jon Skeet - <skeet@pobox.co m>
        Web site: http://www.pobox.com/~skeet
        Blog: http://www.msmvps.com/jon.skeet
        C# in Depth: http://csharpindepth.com

        Comment

        • Howard Swope

          #5
          Re: This works from C#, but not C++ / CLI

          The errors I am getting when I try to inherit from this class with

          public ref class MyDictionary : DictionaryBase< String^, Object^>

          {

          public:

          MyDictionary(vo id);

          };



          are


          Error 1 error C3766: 'MyDictionary' must provide an implementation for the
          interface method 'System::Collec tions::Generic: :IEnumerator<T>
          ^System::Collec tions::Generic: :IEnumerable<T> ::GetEnumerator (void)'

          Error 2 error C3766: 'MyDictionary' must provide an implementation for the
          interface method 'void
          System::Collect ions::Generic:: ICollection<T>: :Add(System::Co llections::Gene ric::KeyValuePa ir<TKey,TValue> )'

          Error 3 error C3766: 'MyDictionary' must provide an implementation for the
          interface method 'System::Collec tions::Generic: :ICollection<T>
          ^System::Collec tions::Generic: :IDictionary<TK ey,TValue>::Key s::get(void)'

          Error 4 error C3766: 'MyDictionary' must provide an implementation for the
          interface method 'System::Collec tions::Generic: :ICollection<T>
          ^System::Collec tions::Generic: :IDictionary<TK ey,TValue>::Val ues::get(void)'

          "Pavel Minaev" <int19h@gmail.c omwrote in message
          news:928a2747-8b4d-425f-af39-25c11f66ac8e@a1 g2000hsb.google groups.com...
          Howard Swope wrote:
          >This problem has been bugging me for a while. I have created a collection
          >class and implemented it in a C# library. If I inherit from this class in
          >another C# assembly and it works, but if I inherit from this class in a
          >C++
          >/ CLI assembly it won't compile.
          >>
          >This indicates a problem in the CLR. Can anyone shed some light on this.
          >The
          >class follows:
          >[... snip ...]
          >
          I did not have any trouble compiling this:
          >
          ref class MyDictionary : public DictionaryBase< int, System::String^ >
          {
          };
          >
          If you could post your C++/CLI code here, and the error message you
          get, we could probably tell you more (though it would be somewhat
          offtopic in a C# group, I guess).
          >
          One thing though - are you sure you did not forget "ref" in your C++/
          CLI class declaration?

          Comment

          • Mark Salsbery [MVP]

            #6
            Re: This works from C#, but not C++ / CLI


            "Howard Swope" <howard.swopeAT navteqDOTcomwro te in message
            news:ONmuqGn8IH A.4988@TK2MSFTN GP04.phx.gbl...
            The errors I am getting when I try to inherit from this class with
            >
            public ref class MyDictionary : DictionaryBase< String^, Object^>
            >
            {
            >
            public:
            >
            MyDictionary(vo id);
            >
            };
            >
            >
            >
            are
            >
            >
            Error 1 error C3766: 'MyDictionary' must provide an implementation for the
            interface method 'System::Collec tions::Generic: :IEnumerator<T>
            ^System::Collec tions::Generic: :IEnumerable<T> ::GetEnumerator (void)'
            >
            Error 2 error C3766: 'MyDictionary' must provide an implementation for the
            interface method 'void
            System::Collect ions::Generic:: ICollection<T>: :Add(System::Co llections::Gene ric::KeyValuePa ir<TKey,TValue> )'
            >
            Error 3 error C3766: 'MyDictionary' must provide an implementation for the
            interface method 'System::Collec tions::Generic: :ICollection<T>
            ^System::Collec tions::Generic: :IDictionary<TK ey,TValue>::Key s::get(void)'
            >
            Error 4 error C3766: 'MyDictionary' must provide an implementation for the
            interface method 'System::Collec tions::Generic: :ICollection<T>
            ^System::Collec tions::Generic: :IDictionary<TK ey,TValue>::Val ues::get(void)'

            The sample code in the documentation for the DictionaryBase class shows the
            interfaces your derived class needs to implement.

            See:
            Provides the abstract base class for a strongly typed collection of key/value pairs.


            Mark

            --
            Mark Salsbery
            Microsoft MVP - Visual C++


            Comment

            • Jon Skeet [C# MVP]

              #7
              Re: This works from C#, but not C++ / CLI

              Mark Salsbery [MVP] <MarkSalsbery[MVP]@newsgroup.nosp amwrote:

              <snip>
              The sample code in the documentation for the DictionaryBase class shows the
              interfaces your derived class needs to implement.
              >
              See:
              http://msdn.microsoft.com/en-us/libr...onarybase.aspx
              What I *think* Mark is saying (and it makes sense) is that you're
              accidentally deriving from the framework's DictionaryBase class rather
              than yours. Rename your class to Foo and try to derive from it then.

              --
              Jon Skeet - <skeet@pobox.co m>
              Web site: http://www.pobox.com/~skeet
              Blog: http://www.msmvps.com/jon.skeet
              C# in Depth: http://csharpindepth.com

              Comment

              • Howard Swope

                #8
                Re: This works from C#, but not C++ / CLI

                It would have been so nice if that was the case. I changed the name of the
                class to Foo and came up with the same errors.

                I think it is something with the signatures... The IL that C# is producing
                is not like by C++. I know it relates directly to the generics. Because if I
                inherit from this class in C# and then inherit from the newly created class
                in C++. The C++ code will compile.

                for example. I create another class:

                public class StringDictionar yBase : DictionaryBase< string, string>

                {

                public StringDictionar yBase()

                {

                }

                }



                I can inherit from StringDictionar yBase in C++.



                "Jon Skeet [C# MVP]" <skeet@pobox.co mwrote in message
                news:MPG.22faea 3119b44350e83@m snews.microsoft .com...
                Mark Salsbery [MVP] <MarkSalsbery[MVP]@newsgroup.nosp amwrote:
                >
                <snip>
                >
                >The sample code in the documentation for the DictionaryBase class shows
                >the
                >interfaces your derived class needs to implement.
                >>
                >See:
                >http://msdn.microsoft.com/en-us/libr...onarybase.aspx
                >
                What I *think* Mark is saying (and it makes sense) is that you're
                accidentally deriving from the framework's DictionaryBase class rather
                than yours. Rename your class to Foo and try to derive from it then.
                >
                --
                Jon Skeet - <skeet@pobox.co m>
                Web site: http://www.pobox.com/~skeet
                Blog: http://www.msmvps.com/jon.skeet
                C# in Depth: http://csharpindepth.com

                Comment

                • Pavel Minaev

                  #9
                  Re: This works from C#, but not C++ / CLI

                  On Jul 31, 5:17 pm, "Howard Swope" <howard.swopeAT navteqDOTcomwro te:
                  It would have been so nice if that was the case. I changed the name of the
                  class to Foo and came up with the same errors.
                  >
                  I think it is something with the signatures... The IL that C# is producing
                  is not like by C++. I know it relates directly to the generics. Because if I
                  inherit from this class in C# and then inherit from the newly created class
                  in C++. The C++ code will compile.
                  I can compile your code just fine here (if I put the required "using"
                  directives in the C# file, and "#using"/"using namespace" into the C++
                  file). So, no, it's probably nothing to do with signatures and IL, and
                  something with the compilation process. First of all, try to do the
                  same I did - take out the C# class to its own separate file (and
                  compile just that), and C++ class to its own file (and compile just
                  that too, only referencing the library produced from the C# file). If
                  that doesn't work, please provide the complete set of compilation
                  options you've used in both cases.

                  Comment

                  • Howard Swope

                    #10
                    Re: This works from C#, but not C++ / CLI

                    I submitted this as an incident to MS. It turns out that this is a bug in
                    the VS2005 compiler. I didn't mention the version of VC in my post which has
                    probably caused some confusion. The issue has been fixed on VS2008. I
                    appreciate everyone's advice.

                    "Pavel Minaev" <int19h@gmail.c omwrote in message
                    news:ca1747a9-d7ea-40ed-b8d9-a7809275ee97@b1 g2000hsg.google groups.com...
                    On Jul 31, 5:17 pm, "Howard Swope" <howard.swopeAT navteqDOTcomwro te:
                    It would have been so nice if that was the case. I changed the name of the
                    class to Foo and came up with the same errors.
                    >
                    I think it is something with the signatures... The IL that C# is producing
                    is not like by C++. I know it relates directly to the generics. Because if
                    I
                    inherit from this class in C# and then inherit from the newly created
                    class
                    in C++. The C++ code will compile.
                    I can compile your code just fine here (if I put the required "using"
                    directives in the C# file, and "#using"/"using namespace" into the C++
                    file). So, no, it's probably nothing to do with signatures and IL, and
                    something with the compilation process. First of all, try to do the
                    same I did - take out the C# class to its own separate file (and
                    compile just that), and C++ class to its own file (and compile just
                    that too, only referencing the library produced from the C# file). If
                    that doesn't work, please provide the complete set of compilation
                    options you've used in both cases.


                    Comment

                    • Ben Voigt [C++ MVP]

                      #11
                      Re: This works from C#, but not C++ / CLI

                      Howard Swope wrote:
                      I submitted this as an incident to MS. It turns out that this is a
                      bug in the VS2005 compiler. I didn't mention the version of VC in my
                      post which has probably caused some confusion. The issue has been
                      fixed on VS2008. I appreciate everyone's advice.
                      Was it the C++ or C# compiler that had the problem? For example, if you
                      compile the C# code in VS2005, can you use it in VC2008, or must the C# code
                      be recompiled with VS2008?
                      >
                      "Pavel Minaev" <int19h@gmail.c omwrote in message
                      news:ca1747a9-d7ea-40ed-b8d9-a7809275ee97@b1 g2000hsg.google groups.com...
                      On Jul 31, 5:17 pm, "Howard Swope" <howard.swopeAT navteqDOTcomwro te:
                      >It would have been so nice if that was the case. I changed the name
                      >of the class to Foo and came up with the same errors.
                      >>
                      >I think it is something with the signatures... The IL that C# is
                      >producing is not like by C++. I know it relates directly to the
                      >generics. Because if I
                      >inherit from this class in C# and then inherit from the newly created
                      >class
                      >in C++. The C++ code will compile.
                      >
                      I can compile your code just fine here (if I put the required "using"
                      directives in the C# file, and "#using"/"using namespace" into the C++
                      file). So, no, it's probably nothing to do with signatures and IL, and
                      something with the compilation process. First of all, try to do the
                      same I did - take out the C# class to its own separate file (and
                      compile just that), and C++ class to its own file (and compile just
                      that too, only referencing the library produced from the C# file). If
                      that doesn't work, please provide the complete set of compilation
                      options you've used in both cases.

                      Comment

                      • Howard Swope

                        #12
                        Re: This works from C#, but not C++ / CLI

                        I am not sure. The gentleman at Microsoft said that the error was corrected
                        in VS2008. I am locked into 2005 here at work and hadn't even thought to try
                        it. I didn't push for further clarification. MS Said if I made a case that
                        my business was heavily impacted by the problem they would create a hotfix,
                        but I told them not to worry about it. I will probably just rewerite my
                        class in C++ / CLI. It's a pain but not that much work.

                        "Ben Voigt [C++ MVP]" <rbv@nospam.nos pamwrote in message
                        news:elF$tu89IH A.5756@TK2MSFTN GP05.phx.gbl...
                        Howard Swope wrote:
                        >I submitted this as an incident to MS. It turns out that this is a
                        >bug in the VS2005 compiler. I didn't mention the version of VC in my
                        >post which has probably caused some confusion. The issue has been
                        >fixed on VS2008. I appreciate everyone's advice.
                        >
                        Was it the C++ or C# compiler that had the problem? For example, if you
                        compile the C# code in VS2005, can you use it in VC2008, or must the C#
                        code be recompiled with VS2008?
                        >
                        >>
                        >"Pavel Minaev" <int19h@gmail.c omwrote in message
                        >news:ca1747a 9-d7ea-40ed-b8d9-a7809275ee97@b1 g2000hsg.google groups.com...
                        >On Jul 31, 5:17 pm, "Howard Swope" <howard.swopeAT navteqDOTcomwro te:
                        >>It would have been so nice if that was the case. I changed the name
                        >>of the class to Foo and came up with the same errors.
                        >>>
                        >>I think it is something with the signatures... The IL that C# is
                        >>producing is not like by C++. I know it relates directly to the
                        >>generics. Because if I
                        >>inherit from this class in C# and then inherit from the newly created
                        >>class
                        >>in C++. The C++ code will compile.
                        >>
                        >I can compile your code just fine here (if I put the required "using"
                        >directives in the C# file, and "#using"/"using namespace" into the C++
                        >file). So, no, it's probably nothing to do with signatures and IL, and
                        >something with the compilation process. First of all, try to do the
                        >same I did - take out the C# class to its own separate file (and
                        >compile just that), and C++ class to its own file (and compile just
                        >that too, only referencing the library produced from the C# file). If
                        >that doesn't work, please provide the complete set of compilation
                        >options you've used in both cases.
                        >
                        >

                        Comment

                        • Howard Swope

                          #13
                          Re: This works from C#, but not C++ / CLI

                          As the thread mentions I submitted this as a bug to MS. I thought I would
                          post the final email that I received for those interested:

                          As we discussed, I'll go ahead and close this case. It was a pleasure
                          working with you. And as discussed we are marking this case non-dec (you
                          will not be charged for this incident as this is a bug in VC 8.0 compiler).

                          Don't hesitate to let us know if there's anything else we can help you with
                          in the future.



                          Here is a summary of the key points of the case for your records:

                          Problem:

                          You have a C# assembly where you have defined an abstract like
                          this :

                          public abstract class DictionaryBase< TKey,TValue:

                          IDictionary<TKe y,TValue>,

                          ICollection< KeyValuePair<TK ey,TValue,

                          IEnumerable< KeyValuePair<TK ey,TValue,

                          IDictionary,

                          ICollection,

                          IEnumerable,

                          ISerializable,

                          IDeserializatio nCallback



                          Also all the methods are defined in this abstract class. When you inherit
                          from this class into a C++/CLI class following compiler errors are thrown:

                          Error 1 error C3766: 'MyDictionary' must provide an
                          implementation for the interface method
                          'System::Collec tions::Generic: :IEnumerator<T>
                          ^System::Collec tions::Generic: :IEnumerable<T> ::GetEnumerator (void)'



                          Error 2 error C3766: 'MyDictionary' must provide an
                          implementation for the interface method 'void
                          System::Collect ions::Generic:: ICollection<T>: :Add(System::Co llections::Gene ric::KeyValuePa ir<TKey,TValue> )'



                          Error 3 error C3766: 'MyDictionary' must provide an
                          implementation for the interface method
                          'System::Collec tions::Generic: :ICollection<T>
                          ^System::Collec tions::Generic: :IDictionary<TK ey,TValue>::Key s::get(void)'



                          Error 4 error C3766: 'MyDictionary' must provide an
                          implementation for the interface method
                          'System::Collec tions::Generic: :ICollection<T>
                          ^System::Collec tions::Generic: :IDictionary<TK ey,TValue>::Val ues::get(void)'





                          Environment :

                          Eligible Product : Visual Studio 2005 SP1



                          Cause:

                          This is a bug in VC8.0 compiler and its fixed in VC9.0 (Visual
                          Studio 2008) compiler. Currently there is no fix available for VC8.0
                          compiler.



                          You have informed us that you will be able to workaround the issue. If in
                          future you would like to get a fix for this please do let me know. And I
                          would help in submitting the request for fix to the devs. Also as I have
                          already informed that it would be the devs who would check out the
                          feasibility of producing a hotfix for this. It could also turnout that we
                          may / may not get the hotfix for this.

                          I am personally committed to providing excellent customer service and I
                          value any comments and suggestions that you may have. I would appreciate
                          your thoughts on not only the things I did right, but also on how I can
                          continue to improve my service in the future. I want to provide you with
                          this opportunity to make your voice heard. Please mail your feedback to my
                          manager whose contact details are given in my signature below.



                          I wish you all the best. Thank you for choosing Microsoft Developer
                          Support.



                          "Howard Swope" <howard.swopeAT navteqDOTcomwro te in message
                          news:uvg7%23Xb8 IHA.3336@TK2MSF TNGP03.phx.gbl. ..
                          This problem has been bugging me for a while. I have created a collection
                          class and implemented it in a C# library. If I inherit from this class in
                          another C# assembly and it works, but if I inherit from this class in a
                          C++ / CLI assembly it won't compile.
                          >
                          This indicates a problem in the CLR. Can anyone shed some light on this.
                          The class follows:
                          >
                          public abstract class DictionaryBase< TKey,TValue:
                          IDictionary<TKe y,TValue>,
                          ICollection<Key ValuePair<TKey, TValue>>,
                          IEnumerable<Key ValuePair<TKey, TValue>>,
                          IDictionary,
                          ICollection,
                          IEnumerable,
                          ISerializable,
                          IDeserializatio nCallback
                          {
                          protected Dictionary<TKey , TValuedictionar y;
                          >
                          #region Constructors
                          public DictionaryBase( )
                          {
                          dictionary = new Dictionary<TKey , TValue>();
                          }
                          >
                          public DictionaryBase( IDictionary<TKe y,TValuediction ary)
                          {
                          this.dictionary = new Dictionary<TKey ,
                          TValue>(diction ary);
                          }
                          >
                          public DictionaryBase( IEqualityCompar er<TKeycomparer )
                          {
                          dictionary = new Dictionary<TKey , TValue>(compare r);
                          }
                          >
                          public DictionaryBase( int capacity)
                          {
                          dictionary = new Dictionary<TKey , TValue>(capacit y);
                          }
                          >
                          public DictionaryBase( IDictionary<TKe y, TValuedictionar y,
                          IEqualityCompar er<TKeycomparer )
                          {
                          dictionary = new Dictionary<TKey , TValue>(diction ary,
                          comparer);
                          }
                          >
                          public DictionaryBase( int capacity, IEqualityCompar er<TKey>
                          comparer)
                          {
                          dictionary = new Dictionary<TKey , TValue>(capacit y,
                          comparer);
                          }
                          >
                          #endregion
                          >
                          #region Properties
                          public virtual IEqualityCompar er<TKeyComparer
                          {
                          get { return dictionary.Comp arer; }
                          }
                          >
                          public virtual int Count
                          {
                          get { return dictionary.Coun t; }
                          }
                          >
                          public virtual TValue this[TKey key]
                          {
                          get { return dictionary[key]; }
                          set { dictionary[key] = value; }
                          }
                          >
                          public virtual Dictionary<TKey ,TValue>.KeyCol lection Keys
                          {
                          get { return dictionary.Keys ; }
                          }
                          >
                          public virtual Dictionary<TKey , TValue>.ValueCo llection Values
                          {
                          get { return dictionary.Valu es;}
                          }
                          >
                          public virtual bool IsReadOnly
                          {
                          get { return false; }
                          }
                          >
                          public virtual bool IsFixedSize
                          {
                          get { return false; }
                          }
                          >
                          public virtual bool IsSynchronized
                          {
                          get { return false; }
                          }
                          >
                          public virtual object SyncRoot
                          {
                          get { return null; }
                          }
                          #endregion
                          >
                          #region Methods
                          public virtual void Add(TKey key, TValue value)
                          {
                          dictionary.Add( key, value);
                          }
                          >
                          public virtual void Clear()
                          {
                          dictionary.Clea r();
                          }
                          >
                          public virtual bool ContainsKey(TKe y key)
                          {
                          return dictionary.Cont ainsKey(key);
                          }
                          >
                          public virtual bool ContainsValue(T Value value)
                          {
                          return dictionary.Cont ainsValue(value );
                          }
                          >
                          public virtual bool Contains(KeyVal uePair<TKey,TVa lueitem)
                          {
                          if (dictionary.Con tainsKey(item.K ey) &&
                          dictionary[item.Key].Equals(item.Va lue))
                          return true;
                          else
                          return false;
                          }
                          >
                          public override bool Equals(Object obj)
                          {
                          return dictionary.Equa ls(obj);
                          }
                          >
                          public virtual Dictionary<TKey ,TValue>.Enumer ator
                          GetEnumerator()
                          {
                          return dictionary.GetE numerator();
                          }
                          >
                          public override int GetHashCode()
                          {
                          return dictionary.GetH ashCode();
                          }
                          >
                          public virtual void GetObjectData(S erializationInf o info,
                          StreamingContex t context)
                          {
                          dictionary.GetO bjectData(info, context);
                          }
                          >
                          public virtual void OnDeserializati on(Object sender)
                          {
                          dictionary.OnDe serialization(s ender);
                          }
                          >
                          public virtual bool Remove(TKey key)
                          {
                          return dictionary.Remo ve(key);
                          }
                          >
                          public virtual bool Remove(KeyValue Pair<TKey,TValu eitem)
                          {
                          if (dictionary.Con tainsKey(item.K ey) &&
                          dictionary[item.Key].Equals(item.Va lue))
                          {
                          dictionary.Remo ve(item.Key);
                          return true;
                          }
                          else
                          {
                          return false;
                          }
                          }
                          >
                          public override String ToString()
                          {
                          return dictionary.ToSt ring();
                          }
                          >
                          public virtual bool TryGetValue(TKe y key, out TValue value)
                          {
                          if (dictionary.Con tainsKey(key))
                          {
                          value = this[key];
                          return true;
                          }
                          else
                          {
                          value = default(TValue) ;
                          return false;
                          }
                          }
                          >
                          public virtual void CopyTo(KeyValue Pair<TKey,TValu e>[] array,
                          int arrayIndex)
                          {
                          int count = 0;
                          foreach (KeyValuePair<T Key,TValueitem in dictionary)
                          {
                          array[arrayIndex + count] =
                          new
                          KeyValuePair<TK ey,TValue>(item .Key,item.Value );
                          ++count;
                          }
                          }
                          >
                          #endregion
                          >
                          #region IDictionary<TKe y,TValueMembers
                          >
                          void IDictionary<TKe y, TValue>.Add(TKe y key, TValue value)
                          {
                          this.Add(key,va lue);
                          }
                          >
                          bool IDictionary<TKe y, TValue>.Contain sKey(TKey key)
                          {
                          return this.ContainsKe y(key);
                          }
                          >
                          ICollection<TKe yIDictionary<TK ey, TValue>.Keys
                          {
                          get { return this.Keys; }
                          }
                          >
                          bool IDictionary<TKe y, TValue>.Remove( TKey key)
                          {
                          return this.Remove(key );
                          }
                          >
                          ICollection<TVa lueIDictionary< TKey, TValue>.Values
                          {
                          get { return this.Values; }
                          }
                          >
                          TValue IDictionary<TKe y, TValue>.this[TKey key]
                          {
                          get
                          {
                          return this[key];
                          }
                          set
                          {
                          this[key] = value;
                          }
                          }
                          >
                          #endregion
                          >
                          #region ICollection<Key ValuePair<TKey, TValue>Members
                          >
                          void ICollection<Key ValuePair<TKey,
                          TValue>>.Add(Ke yValuePair<TKey , TValueitem)
                          {
                          this.Add(item.K ey,item.Value);
                          }
                          >
                          void ICollection<Key ValuePair<TKey, TValue>>.Clear( )
                          {
                          this.Clear();
                          }
                          >
                          bool ICollection<Key ValuePair<TKey,
                          TValue>>.Contai ns(KeyValuePair <TKey, TValueitem)
                          {
                          return this.Contains(i tem);
                          }
                          >
                          void ICollection<Key ValuePair<TKey,
                          TValue>>.CopyTo (KeyValuePair<T Key, TValue>[] array, int arrayIndex)
                          {
                          this.CopyTo(arr ay,arrayIndex);
                          }
                          >
                          int ICollection<Key ValuePair<TKey, TValue>>.Count
                          {
                          get { return this.Count; }
                          }
                          >
                          bool ICollection<Key ValuePair<TKey, TValue>>.IsRead Only
                          {
                          get { return this.IsReadOnly ; }
                          }
                          >
                          bool ICollection<Key ValuePair<TKey,
                          TValue>>.Remove (KeyValuePair<T Key, TValueitem)
                          {
                          return this.Remove(ite m);
                          }
                          >
                          #endregion
                          >
                          #region IEnumerable<Key ValuePair<TKey, TValue>Members
                          >
                          IEnumerator<Key ValuePair<TKey, TValue>>
                          IEnumerable<Key ValuePair<TKey, TValue>>.GetEnu merator()
                          {
                          return this.GetEnumera tor();
                          }
                          >
                          #endregion
                          >
                          #region IEnumerable Members
                          >
                          IEnumerator IEnumerable.Get Enumerator()
                          {
                          return this.GetEnumera tor();
                          }
                          >
                          #endregion
                          >
                          #region IDictionary Members
                          >
                          void IDictionary.Add (object key, object value)
                          {
                          this.Add((TKey) key,(TValue)val ue);
                          }
                          >
                          void IDictionary.Cle ar()
                          {
                          this.Clear();
                          }
                          >
                          bool IDictionary.Con tains(object key)
                          {
                          return this.ContainsKe y((TKey)key);
                          }
                          >
                          IDictionaryEnum erator IDictionary.Get Enumerator()
                          {
                          return this.GetEnumera tor();
                          }
                          >
                          bool IDictionary.IsF ixedSize
                          {
                          get { return this.IsFixedSiz e; }
                          }
                          >
                          bool IDictionary.IsR eadOnly
                          {
                          get { return this.IsReadOnly ; }
                          }
                          >
                          ICollection IDictionary.Key s
                          {
                          get { return this.Keys; }
                          }
                          >
                          void IDictionary.Rem ove(object key)
                          {
                          this.Remove((TK ey)key);
                          }
                          >
                          ICollection IDictionary.Val ues
                          {
                          get { return this.Values; }
                          }
                          >
                          object IDictionary.thi s[object key]
                          {
                          get
                          {
                          return this[(TKey)key];
                          }
                          set
                          {
                          this[(TKey)key] = (TValue)value;
                          }
                          }
                          >
                          #endregion
                          >
                          #region ICollection Members
                          >
                          void ICollection.Cop yTo(Array array, int index)
                          {
                          this.CopyTo((Ke yValuePair<TKey ,TValue>[])array,index);
                          }
                          >
                          int ICollection.Cou nt
                          {
                          get { return this.Count; }
                          }
                          >
                          bool ICollection.IsS ynchronized
                          {
                          get { return this.IsSynchron ized; }
                          }
                          >
                          object ICollection.Syn cRoot
                          {
                          get { return this.SyncRoot; }
                          }
                          >
                          #endregion
                          >
                          #region ISerializable Members
                          >
                          void ISerializable.G etObjectData(Se rializationInfo info,
                          StreamingContex t context)
                          {
                          this.GetObjectD ata(info,contex t);
                          }
                          >
                          #endregion
                          >
                          #region IDeserializatio nCallback Members
                          >
                          void IDeserializatio nCallback.OnDes erialization(ob ject sender)
                          {
                          this.OnDeserial ization(sender) ;
                          }
                          >
                          #endregion
                          }
                          >
                          >
                          --
                          Howard Swope [ mailto:howard.s wopeATnavteqDOT com ]
                          Technical Lead
                          Media Development
                          Navteq Traffic [ http://www.navteq.com ] [ http://www.traffic.com ]
                          >

                          Comment

                          Working...