Jump to content
Xtreme .Net Talk

Mike_R

Avatar/Signature
  • Posts

    316
  • Joined

  • Last visited

Everything posted by Mike_R

  1. True, you don't need 'ByRef' here, since you aren't changing the instance, so, yes, 'ByVal' makes more sense. But this isn't your problem (as you said). I have no clue, I'm afraid... Are you saying that the 'doc As Word.Document' parameter is coming through as 'Nothing' even though the argument passed in is non-null?? Can you show your code, including your logging calls for your LoadDoc method?
  2. I'm not a Word programmer, but your code looks ok to me. I think you'll have to trace this with debugging tools. Trace the actual assignment of '_document = doc' to make sure this is getting set right. (It must, but, well, trace it anyway...) Then put have a breakpoint within the method that gets called when you click a toolbar button. Then trace/step into that code as well to see what is going on. - Mike
  3. I'm glad it helped (at least a little). You might want to try something like: oGraph.Application.DataSheet.Range("A1:C3").Value And see if you can get a 2D array of values or set a 2D array of values in one shot. It will either work or you'll get an exception, but it couldn't hurt to try, right?
  4. Hey John, I'm sorry to say, but I do not have a clue about the PowerPoint object model. Using the PowerPoint object browser in VBA, I cannot even find the Application.DataSheet member. Odd... The examples I see online seem to use the same "cell-by-cell" approach that you are using. (For example: here. However, there seems to be a mechanism for importing an Excel spreadsheet into a chart, so that might be the way to go, if you can figure it out. Sorry I can't help more, but I'm not a PowerPoint guy...
  5. Sure, no problem, glad it helped! :), Mike
  6. Re: A demonstration Yeah, I think you got it. And, and unfortunately, this would be a reverse-compatibility issue if they changed it. However, one could envision a world where the '+' operator is overloaded for 'byte' and 'short', in that case: byte b = 250; b = b + b; would return 244 (or throw an exception if checked), instead of returning 500. If you wanted to get the behavior shown in your 'short s = (short) (b + b);' example then one would have to explicitly cast at least one of the operands: byte b = 250; short s = (short)b + b; I really think that this is the way it "should" be, the more I think about it... but there would be reverse-compatibility issues if they did this now, as highlighted by your example. My guess as to why they do it this way is that this would take *extra* steps to execute overflow behavior for 8 bits or 16 bit types, which wouldn't overflow when using native 32 bit arithmetic. Still, the "explicit cast approach" would allow one to force 32 bit calculations -- but it would take extra coding (an explicit cast) to force the more efficient execution. This brings up something related though... How does the following execute on a 64 bit machine? int i = int.MaxValue; long l = i + i; I don't have access to a 64 bit machine, but I'll guess that it would have to assign -2 to the 'long l' value, right? Otherwise there would be massive compatibility issues depending on whether the code is running on a 32 bit or 64 bit machine. But this would also mean that an "artificial overflow" concept (extra code checks) would be in force here for 'int + int', but not for 'byte + byte' or 'short + short'. Kind of interesting...
  7. Re: Compiler evaluation Ok, fair enough... But 'b + b' is a compile time error, not a run-time error, so this still leaves us with the fact that '++' and '+=' appear to be explicitly overloaded for 'byte' and 'short' whereas '+' upcasts to integer instead, but then you get snagged when assigning the return value.
  8. Re: Option Strict On Actually, while we're on the subject... how is it that the following is legal in C# without an explicit cast: byte b = 0; b = 1; Or this: byte b = 0; b = 1 + 1; But not this: byte b = 0; b = b + b; // <-- Compile time error. Kinda weird, eh? Seems to be some compiler "help" in some circumstances, but not in others. I'm wondering what the rule is here. (Is there a rule?)
  9. Re: Option Strict On Well, VB.NET is trying to be helpful when in 'Option Strict Off' here, and I think that it is. In most other cases, though, you really do want to be forced to make your casts explicit, so 'Option Strict On' really is pretty much a necessity. The same thing happens in C#, although not with the '+=' or '++' operator. The problem is that the '+' operator is defined for integer, but not for byte or short, so byte and short operands are upcasted to integer, added together, and then returned as an integer. So when returning the result back to the byte it needs to be explicitly cast back: On the other hand, the '++' and '+=' operators are overloaded to accept and return byte: byte b = 0; b++; // <-- Ok b += 1; // <-- Ok b = b + b; // <-- Compile time error! The compiler's complaint on the last line is: "Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)" And so we're required to use: b = (byte)(b + b); I don't see why the '+' operator could not be overloaded in a future version in order to directly handle byte and short data types (instead of upcasting). It would seem to make more sense that '+' operate by the same rules as '+=' and '++'. I guess the problem with trying to change this the issue of overflow, esp. when we could have two flavors: unchecked or checked. Still, I think it's an uncomfortable situation that '++' and '+=' are operating differently, allowing implicit casts whereas '+' does not.
  10. Ok, thanks PD for clearing that up. :-) Funny, I had thought it was the other way around: that the CLR would not be taking extra steps like this and that VB.NET was "injecting code" to zero it out. Funny, then, that C# does not enforce field initializers? It would seem much easier to enforce that a field is initialized at the point of declaration (or within all constructors) than the complex path analysis that C# must undergo for variables? C# seems to be saying that it's ok to assume that a field will be the default null/0/false but it's not ok to assume the same for a variable? Anyway, thanks for solving this mystery for me, PD. One less thing keeping me up at night... :)
  11. I was thinking about how VB.NET auto-initializes its variables if not explicitly written to before being read, something that C# does not allow. The simplest example would be something like this: ' VB.NET: Public Sub MySub() Dim j As Integer MessageBox.Show(j.ToString) End Sub The equivalent in C# would not compile: // C#: public void MySub() { int j; MessageBox.Show(j.ToString()); } The compiler would complain about "Use of unassigned local variable 'j'" at the point where 'j.ToString()' is called. So I wondered what the VB.NET code would look like when viewing the IL. I had expected to find an explicit assignment of 'j' to 0, presumably created by the VB.NET compiler. But I was surprised at what I found: .method public instance void MySub() cil managed { .maxstack 1 .locals init ( [0] int32 j) L_0000: ldloca.s j L_0002: call instance string [mscorlib]System.Int32::ToString() L_0007: call valuetype [system.Windows.Forms]System.Windows.Forms .DialogResult [system.Windows.Forms]System.Windows.Forms .MessageBox::Show(string) L_000c: pop L_000d: ret } Basically, the 'int32 j' is not assigned a value before .ToString() is called. I had expected to see 'j' being set to zero via a 'ldc.i4.0' call followed by 'stloc.0' and then the rest of the routine would proceed as shown above. That is, I had expected to see this: .method public instance void MySub() cil managed { .maxstack 1 .locals init ( [0] int32 j) L_0000: ldc.i4.0 L_0001: stloc.0 L_0002: ldloca.s j L_0003: call instance string [mscorlib]System.Int32::ToString() L_0004: call valuetype [system.Windows.Forms]System.Windows.Forms .DialogResult [system.Windows.Forms]System.Windows.Forms .MessageBox::Show(string) L_0005: pop L_0006: ret } So does the CLR itself zero out all variables? And therefore VB.NET is not really "doing anything", but instead is merely allowing the default behavior to occur, whereas C# is being more restrictive? Or is there a CIL setting, attribute, or the like somewhere that determines whether unassigned memory should be zeroed out before use automatically? (A setting that VB.NET would be using, but not C#?) Anyway, I was wondering if anyone here knew what was going on... Mike
  12. You could also try the 'Microsoft.VisualBasic.Strings.Split' method, which can also handle a multi-character string splitter. It might handle your "last character" issue better, don't know... I think it's also a little safer to use in general than RegEx.Split(), unless you really do wish to split on a pattern. In your case you are passing in Cr & Lf, so it's fine, but if you passed in "\d", for example, all heck would break loose, splitting on every digit... You know the source in this case, so it's ok, but if you don't know what the spit value will be beforehand (supplied by the user, perhaps?) then you could get really snagged with RegEx.Split, I think.
  13. Ah, thank you mskeel! Using #if DEBUG ... #endif blocks will definitely be the way to go for me. I did not realize that the #if directive could be used to surround an entire class. This is beautiful and does exactly what I need. (I had thought that it could only be used within a method.) Maybe, I'm not quite decided on this yet. I am just taking around the idea at this point. But I think that it makes a lot of sense at a lot of levels... I have no real problems with NUnit or the like. But, yes, the main idea I'm shooting for here is to have the testing code be as physically close to the implementation as possible. It makes it easier to make and test, and it makes everything more portable: if I copy and paste, or re-factor and move the class, the test code moves right with the class that is being tested. Since NUnit works using reflection, keying on various attributes, I wonder if I might be able to simply use NUnit and still use internal, nested testing classes. I've not tested this though -- since NUnit uses reflection, a public class should not be required here, but it is possible that it still respects public vs private/internal and only executes public classes that have the correct attributes? But I don't know... Also since NUnit's methods are also void methods, without any out parameters, if this works then I could simply use a [Conditional("DEBUG")] attribute for each method in the class in this case. However, your idea to use #if ..#endif blocks to surround the entire class and more effective. Anyway, just thinking out loud at the moment, I guess... Mike
  14. I have nothing against NUnit or the like, I think that these unit-testing programs really are excellent... But more and more it's been bothering me that the testing code is separate from the class that is being testing. So I decided to put my testing code for each class within an internal, nested class named "Tester", nested within the class being tested. I then use the assembly:InternalsVisibleToAttribute to enable my testing assembly -- and only my testing assembly -- to have access to this testing code. So far, so good... However, for my last step, I would like to prevent this testing code from being emitted to CIL when compiled as a release build. My first thought was to use the [Conditional("DEBUG")] attribute, however, the ConditionalAttribute cannot be used with methods that have a non-void return value, nor with methods that have out parameters. :( Using partial methods would be extremely awkward, and would suffer from the same problem... My only other thought is to use the [Conditional("DEBUG")] attribute using void methods and return my results to a static global field. Since all my testing is single threaded anyway, this would work fine... But it does feel pretty crude. :( Does anyone have any other ideas? Is there any other way to suppress a method from being compiled to the CIL? Thanks guys, in advance... Mike
  15. I have no solutions for you... However, I think that a related question is: how do you guarantee that there is a single, unique solution? That is, the starting position for your board should fill in enough squares so that there is only one possible solution without filling in too many, or else the problem will be to easily solved. If the starting position does not guarantee a single, unique solution, then your "hint" functionality becomes much more complicated! I suppose that your hint could show any one of several valid values, or perhaps show them all? Ideally, however, you're starting board should only allow for one possible solution... If that is the case, then your hint functionality will be easier to implement. Unfortunately my thoughts here are not of much help! You need some sort of solution algorithm, and that same algorithm would be used to determine if there is only one unique solution, as well as be used for your hint functionality... (I hope this helps in some small way? Probably not...)
  16. Hey PD, I think we're on the same page... If anything, you're probably just mystified as to why I even found this interesting?! Basically, I was initially confused by the fact that the following will not compile: IMyInterface obj = new MyClass(); using (obj) { obj.SomeMethod(); } But this is not a huge mystery in that IMyInterface does not implement IDisposable. However the 'obj' reference in question in this case does implement IDisposable because it holds a reference to a MyClass object. But the compiler can't know that... I found the following solution interesting in that the 'obj' in question could function as an IMyInterface -- as exhibited by the successful call to obj.SomeMethod() -- and yet simultaneously operate 'as IDisposable': IMyInterface obj = new MyOtherClass(); using (obj as IDisposable) { obj.SomeMethod(); } It took me a bit, but it turns out I was simply a little too hung up on the slightly-oversimplified explanation of the using statement that Juval Lowy provided in his book: try { obj.SomeMethod() } finally { if (obj != null) obj.Dispose(); } In the above, the compiler should not be able to verify that 'obj.SomeMethod()' and 'obj.Dispose()' both work and therefore should fail to compile. This is because SomeMethod() is a member of IMyInterface while Dispose() is a member of IDisposable, and the 'obj' cannot be cast to both IMyInterface and to IDisposable at the same time. Admittedly, this example shown by Lowy was mearly meant to be demonstrative, as a simplification... And I took it a bit too literally. That said, for the picky among us (and I guess that includes me!) the correct translation must be more like the following: IDisposable _temp = obj as IDisposable; try { obj.SomeMethod() } finally { if (_temp != null) _temp.Dispose(); } So, anyway, no great mystery, but there was a contradiction, at least the way I was looking at it. Thanks for helping me get to the bottom of it, even if I was the only one who was confused!
  17. Nice explanation. :-) But I'm not sure that I agree with all of it... I'm not sure that this is right... What you say about the debugger may be true, but the debugger is running at runtime. Note that the following code does not compile: IMyInterface obj = new MyClass(); using (obj) { obj.SomeMethod(); } (In fact, this is actually the start of this entire exercise.) Because the IMyInterface interface does not implement IDisposable, the 'obj' stored as an IMyInterface reference cannot be used directly within a using statement. But the above does still have one minor remaining issue. It must test if the value passed into the using statement is null from within the finally block. Therefore, this value must be stored within a temporary variable. Not to be picky, but my thinking currently is that the following representation of a using statement -- which is how Juval Lowy shows it on p.94 of his book -- is not *quite* correct: try { obj.SomeMethod() } finally { if (obj != null) obj.Dispose(); } I think that it must be something like this: private IDisposable __hiddenObj = obj as IDisposable; try { obj.SomeMethod() } finally { if (__hiddenObj != null) __hiddenObj.Dispose(); } This is only a subtle change, but I think this is essentially the only way to achieve the simultaneous casting of two interfaces for one object: you need a second variable.
  18. Yes, I understand how it works... (I should have mentioned the 'if (obj != null)' check in the finally statement.) But you are right in that I was making a mistake of considering the 'as' operator as a compile time check, instead of as the runtime check that it is. But this alone does not get us out of hot water... The mystery that remains is that 'obj' is cast both as IMyInterface -- allowing for the 'obj.SomeMethod()' call -- while simultaneously allowing for the 'cast as IDisposable' call to also be in play... that is 'obj.SomeMethod()' will always work, and yet the check for 'obj != null' within the finally statement may or may not return true. For example, if the former works (which it does) then the following should fail at runtime: First let's create a new class 'MyOtherClass', which implements IMyInterface but does NOT implement IDisposable: class MyOtherClass : IMyInterface { void IMyInterface.SomeMethod() { MessageBox.Show("IMyInterface.SomeMethod() called."); } } then let try calling the following code: IMyInterface obj2 = new MyOtherClass(); using (obj2 as IDisposable) { obj2.SomeMethod(); } One would think that 'obj2 as IDisposable' would return null (it has to) and yet, somehow, call to 'obj2.SomeMethod()' *succeeds* while presumably the null check within the implied finally block of the using statement indicates that the object is also null (because 'obj2 as IDisposable' must return null). I suppose the answer is that something special is going on here... 'obj' is not null for it does not receive the result of 'obj2 as IDisposable'. That is, the call isn't an assignment such as 'obj2 = obj2 as IDisposable', in which case obj2 would indeed be null. So here 'obj2' remains non-null and the call to 'obj2.SomeMethod()' succeeds... Therefore, the result of 'obj2 as IDisposable' must be assigned to some temporary variable, and it is this variable that must be checked within the finally statement. One would have to look at the generated IL code to be certain, but I think that this must be it. Mystery solved.
  19. I stumbled upon the following code in Juval Lowy's "Programming .NET components" on pages 95-96. The following is pretty much as he shows it, with the addition of a couple of MessageBox calls: internal interface IMyInterface { void SomeMethod(); } internal class MyClass : IMyInterface, IDisposable { void IDisposable.Dispose() { MessageBox.Show("IDisposable.Dispose() called."); } void IMyInterface.SomeMethod() { MessageBox.Show("IMyInterface.SomeMethod() called."); } } public static void Run() { IMyInterface obj = new MyClass(); using (obj as IDisposable) { obj.SomeMethod(); } } The above code runs fine... but this is exactly what I'm questioning... The point that Lowy was making is that while this code is run fine: MyClass obj = new MyClass(); using (obj) { obj.SomeMethod(); } The following code does not compile: IMyInterface obj = new MyClass(); using (obj) { obj.SomeMethod(); } The reason is that the IMyInterface interface does not itself implement IDisposable. We could correct this situation by having IMyInterface implement IDisposable: internal interface IMyInterface: IDisposable { void SomeMethod(); } But this would be a ludicrous requirement just so that a 'using' statement could be utilized more easily; certainly not all classes implementing IMyInterface would also need to implement IDisposable. So the solution that Juval Lowy shows is the following: public static void Run() { IMyInterface obj = new MyClass(); using (obj as IDisposable) { obj.SomeMethod(); } } To my surprise, it does compile and run 100% fine. But what is going on here? Calling 'obj.SomeMethod()' is really a call to 'IMyInterface.SomeMethod()' and so the 'obj' is still cast as 'IMyInterface'. And yet the using statement accepts the cast to IDisposable at the same time! Admittedly, a 'using' statement does not actually "require" an IDisposable object; the object merely needs to have a method called "Dispose()", and reflection is done at compile time to enforce that the "Dispose()" method does indeed exist. But somehow, I don't think that this is what's going on here. It does seem to be a "simultaneous cast" of sorts... Does anyone have any thoughts?
  20. Hey Andy, Assuming that at least Cell A1 has some data in it (you might want to check first to make sure) you could use the Range.End() method. For example, using VB.NET, you could do something like this: Dim rng As Excel.Range = xlSheet.Range("A1") rng = rng.End(Excel.XlDirection.xlDown) C# is the same, really: Excel.Range rng = xlSheet.get_Range("A1", Type.Missing); rng = rng.End(Excel.XlDirection.xlDown); This only works though if the column has no empty cells within the column, otherwise it will stop at the first gap. If there are gaps, you might want to come up from the bottom: Dim rng As Excel.Range = _ CType(xlSheet.Cells(xlSheet.Rows.Count, 1), Excel.Range) rng = rng.End(Excel.XlDirection.xlUp) In C#: Excel.Range rng = (Excel.Range) xlSheet.Cells(xlSheet.Rows.Count, 1); rng = rng.End(Excel.XlDirection.xlUp); Hope this helps! Mike
  21. Ah, thanks so much PD, that was perfect. :) I had looked under the Project Properties > Build page, but there's not setting for this there. Thanks a ton for pointing out the correct location! Mike
  22. Hi guys, I was wondering if anyone knew of a way to prevent the VS IDE from automatically saving my assemblies when I choose 'Build'? Yes, I do realize that saving the source code at the same time that the exe or dll is compiled makes sense. This ensures that they are the same version... But it can also make sense to *not* have this behavior. While VB.NET has background compilation, C# does not. So if using VB.NET, any change that causes a code break is flagged immediately. In C#, however, one is forced to manually chose 'Build' to see if there are any problems... So let's say that I do some sort of complex Regex-based find/replace operation. I'm careful, and among other things I save my work before performing the Regex find-replace. This way if the find/replace somehow goes wildly wrong and causes dozens of code breaks (or even one, really), then I can either Undo or to be really safe, close without saving the most recent (bad) change. It's just a good safety precaution. But using C#, there's a problem: there is no way to know for certain if there are any code breaks without first choosing 'Build'. But choosing 'Build' not only compiles the solution, but also saves the unsaved changes. This is not good for this scenario... Does anyone know of a way to achive a build/compile operation without saving at the same time? Thanks for any thoughts in advance... Mike
  23. Hey PD, Thanks for your thoughts. I agree with everything you said here. Although, I think there can be another aspect to some of them... I agree here and this might be the case for me since I am only just now moving from VB.NET to C#. For methods, I agree 100% that 'ClassName.MethodName' is much clearer and safer. However, I would personally not mind an exception whereby Enum types were allowed to be imported, allowing calls to show the Enum field name without having to utilize the 'EnumType.EnumFieldName' construct always. This is only a minor annyance however, but is an area where VB.NET code does look nicer. Agreed. But I think the bigger issue is that method calls should not be divorced from the containing type, as you stated above. Yes, true. But this can currenly occur with a newly-introduced type. So method name and namespace name clashes cannot occur in future versions using C#, but a type-name collision could happen. So C# is safer than VB on this mark, but not immune. The reason that I wanted to be able to import a Namespace that did not contain any types, was so that I could simplify namespaces such as the following: AcmeProgramming.AcmeBase AcmeProgramming.AcmeMidTier AcmeProgramming.AcmeUserIO Using VB.NET I can shorten the lengthes of all three of these in one shot: Imports AcmeProgramming And now I can just call 'AcmeBase' or 'AcmeMidTier', etc., directly. However, I was suprised to find that C# did not let me do this. But MrPaul pointed out the solution, above: using AcmeBase = AcmeProgramming.AcmeBase using AcmeMidTier = AcmeProgramming.AcmeMidTier using AcmeUserIO = AcmeProgramming.AcmeUserIO I've not seen this yet, but I doubt it would be *too* hard to disambiguate? Best would be if the compiler error stated the full namespace path to the types which could be viable. If not, then yeah, might have to go back to an earlier version and compare. Not fun :( Thanks PD, Mike
  24. Re: Importing empty namespaces? Ok, I thought of a small, but nice advantage that C# namespaces have: you can use the using statement within a namespace, instead of being for the entire project or entire document. This is better encapsulation and certainly makes it more portable as well, if you need to move a namespace out of the document into another document or project. Still, they do seem to be extremely similar overall...
  25. Re: Importing empty namespaces? Hey MrPaul, Thanks for your thoughts, they were good ones. Yeah, I guess I didn't give a very good example there. It certainly wasn't practical. A more practical example is when you have, say, two or more assemblies, whose names use the standard CompanyName.TechnologyName naming convention. For example, "Microsoft.Win32" or whatever. In this situation, I would like to import the 'CompanyName' namepace so that I can directly access the next level (which tends to have shorter names). Ah, yes, thank you! This is exactly what I was looking for. Much thanks. I have. More than once. The most recent time I saw it was from an experienced C# programmer. It's in a private forum, or I'd give a link. It did make me curious. Best I can tell they do seem almost identical. Thanks for getting me unstuck on this though. It's very much appreciated... Mike
×
×
  • Create New...