Toon posts:

[.NET/C#/COM+] C# compiler geeft vage error

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hieronder een stukje testcode dat dezelfde error produceert als mn gegeneerde code. Het gaat om de regel onder *COMPILERERROR*. Aldaar krijg ik de error:
C:\Myprojects\VS.NET Projects\csctst\Class1.cs(35): Cannot pass 'csctst.Foo.m_iErrorCode' as ref or out, because
'csctst.Foo.m_iErrorCode' is a marshal-by-reference class
Deze error krijg ik NIET, wanneer ik .ToString() weghaal. Ook als ik de base class niet laat deriven van ServicedComponent, krijg ik de error niet wanneer ik .ToString() specificeer.

Op zich snap ik totaal niet waarom de error wordt gegeven, omdat .ToString() een string teruggeeft en deze dus gewoon aan de constante string moet plakken. Ergo: kan iemand wellicht meer duidelijkheid verschaffen?

ps: ik weet dat een protected property het oplost. Echter dat zou net zo fout moeten zijn icm met die .ToString(). Wellicht een bug in de Compiler, of een misverstand aan mijn kant.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;
using System.EnterpriseServices;

namespace csctst
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class Foo : ServicedComponent
    {
        protected int m_iErrorCode;
    
        public Foo()
        {
            // nothing
        }   
        
    }
    
    
    class Bar : Foo
    {
    
        public Bar()
        {
            // nothing
        }
        
        public void DoSomething(int iValue)
        {
            m_iErrorCode = iValue;
            
            if(m_iErrorCode!=0)
            {
                      // *COMPILERERROR*
                throw new Exception("Error occured: invalid value passed: " + m_iErrorCode.ToString());
            }
        }
    
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            //
            // TODO: Add code to start application here
            //
            Bar bTest = new Bar();
            
            bTest.DoSomething(1);
        }
    }
}

  • whoami
  • Registratie: December 2000
  • Laatst online: 07-09 19:30
Hm, inderdaad vaag.

Ik heb even in de help gekeken die bij de SDK zit:
Cannot pass 'argument' as ref or out, because ' argument ' is a marshal-by-reference class

Any class that derives (directly or indirectly) from System.MarshalByRefObject is a "marshal-by-reference" class. Such a class can be marshaled by reference across process and machine boundaries. Thus, instances of this class could be proxies to remote objects. You cannot pass a field of a proxy object as ref or out. So, you cannot pass fields of such a class as ref or out, unless the instance is this, which can never be a proxy object.

The following sample generates CS0197:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// CS0197.cs
using System;
class X : MarshalByRefObject
{
   public int i;
}

class M
{
   public int i;
   static void AddSeventeen(ref int i)
   {
    i += 17;
   }

   static void Main()
   {
    X x = new X();
    x.i = 12;
    AddSeventeen(ref x.i);   // CS0197
    // try the following lines instead
    // M m = new M();
    // m.i = 12;
    // AddSeventeen(ref m.i);
   }
}
maar hier zijn we eigenlijk niet zoveel mee, omdat in uw geval er geen waarden doorgegeven worden als ref of out parameters.

Misschien dat je bij www.gotdotnet.com of www.dotnet.be meer kunt geholpen worden...

https://fgheysels.github.io/


  • DolleDries
  • Registratie: Oktober 2000
  • Laatst online: 22-08 11:46
Euhr...zal aan mij liggen, maar waarom heb je die error value een protected member gemaakt. Daardoor kan je niet overerven en zal deze niet bereikbaar zijn in die tweede class.

een object georienteerd probleempje dus.
Maak er eens private of public van en je probleem is verholpen. zo dacht ik 8-)

  • whoami
  • Registratie: December 2000
  • Laatst online: 07-09 19:30
een protected member is juist wel bereikbaar vanaf een child-class. Een private is dat juist niet.

https://fgheysels.github.io/


Verwijderd

Topicstarter
Op dinsdag 21 mei 2002 16:45 schreef DolleDries het volgende:
Euhr...zal aan mij liggen, maar waarom heb je die error value een protected member gemaakt. Daardoor kan je niet overerven en zal deze niet bereikbaar zijn in die tweede class.

een object georienteerd probleempje dus.
Maak er eens private of public van en je probleem is verholpen. zo dacht ik 8-)
Hij is protected omdat in de productiecode waar ik de compiler error kreeg, de ErrorCode member in een abstract baseclass zit. Zodoende is hij private voor alle derived classes van die baseclass, en accessable en publique via een property (bv gebruik makend van de derived class). Alleen de derived classes werken met de protected member, vandaar dat het een goede oplossing is.

Het probleem zit hem in de .ToString() call. Als je in de derived class specificeert:

string sTest = m_iErrorCode.ToString();

krijg je dezelfde error.
Doe je:

string sTest = m_iErrorCode.GetType().FullName;

dan krijg je de error niet.
(GetType().FullName is de object.ToString() implementatie van Rotor).

Ik heb ff in Rotor (de shared source CLR implementatie) gekeken en Rotor's code geeft voor de Int32.ToString():
code:
1
2
3
4
5
6
7
      public override String ToString() {
        return ToString(null, null);
      }

      public String ToString(String format, IFormatProvider provider) {
        return Number.FormatInt32(m_value, format, NumberFormatInfo.GetInstance(provider));
      }

Hier krijg je dus eigenlijk inzicht in de error: m_value wordt naar buiten gepassed, alleen IMHO (en vandaar dus een compiler bug) by value.

In de C# newsgroup van microsoft zelf nog niets gehoord (daar zitten ook de C# compiler bouwers), behalve nog iemand die dezelfde error had.

Ut blijft vaag. Naja, laat eerste de '+' concatenatie zonder .ToString() wel staan. In principe doet die exact hetzelfde.

Verwijderd

Topicstarter
code:
1
throw new Exception(String.Format("Error occured: invalid value passed: {0}", m_iErrorCode));

werkt dus wel.

Erg vaag dit. :) Naja, de bovenstaande workaround is elegant genoeg om ermee door te kunnen. Maar vaag is het wel.
Pagina: 1