I would like to use Delegation on my Kotlin project, but I have a peculiar requirement. The delegation object itself should hold a reference to the parent object. To give you an example let's consider the following code:
interface MyInterface
class MyImpl(val a: MyTest?) : MyInterface
class MyTest : MyInterface by MyImpl(null)
What I'd like to do is replace null above with a this reference to MyTest object. But compiler doesn't let me with the error
'this' is not defined in this context
When I decompile the produced code, I get something like
public final class MyTest implements MyInterface
{
private final /* synthetic */ MyImpl $$delegate_0;
public MyTest() {
this.$$delegate_0 = new MyImpl(null);
}
}
which would seem perfectly legal, if I wanted to pass this instead of null when the delegate is initialized. But I can't figure how to do it. Is it a Kotlin's restriction or am I doing something wrong?
I know that I can bypass this restriction by using a var inside MyImpl and give a reference to parent.this at later time on my code. But this would mean that MyImpl will have a mutable reference of something that could be val instead, and I don't think this solution is elegant enough.
In JavaScript, and other Object oriented languages, you can instantiate a new instance of a class, and use a method of the class instance in the same line. For example:
class customClass {
method(){
return "hello"
}
}
var s = (new customClass).method() // s = "hello"
If I try the same in VBA:
s = (new customClass).method()
I get a Compile error: Expected: end of statement, while highlighting the . after customClass).
If you like you can do the following:
Dim c as new customClass: s=c.method()
however in this case, in my opinion, it is not clear that s is being set at all making code more difficult to manage.
Is there an alternative method which makes the line clearer to understand, while still being quick and easy to write?
Sure you can.
With New Collection: .Add 42: Debug.Print .Count: End With
I'd probably want to chew the head off whoever put that in production code, but sure you can.
Doesn't mean you should.
Note that for some reason you don't get IntelliSense for With block variable references in such inline With blocks.
May or may not have something to do with VBA code shouldn't be written like this.
If the method you want to invoke doesn't alter global or instance state, consider specifying a VB_PredeclaredId module attribute on your class instead (export the module, edit its header in Notepad, re-import the module).
That way this code becomes legal, and looks much more VBA-idiomatic:
SomeCustomClass.SomeMethod
The mechanics are identical to those involved when people do UserForm1.Show off the default instance, without creating a New object.
You can pass a new instance of a class to the CallByName Function and have it access the method for you.
Dim s As String: s = CallByName(New customClass, "method", VbMethod)
Currently I have thought of 2 methods of solving the problem.
The first method I came up with is a bit hacky, but it does the trick:
s = Array(new someClass)(0).method()
However in general this method is quite confusing and difficult to read... So instead I figured you could just use a helper function instead:
function proxy(a as variant) as variant
if isObject(a) then
set proxy = a
else
proxy = a
end if
end function
sub textProxy()
s = proxy(new someClass).method()
debug.print s
end sub
It is a shame however that you lose the intelisense in both of these examples... But I guess that's more of a problem with the VBE than the methods themselves.
Can someone please tell what the following line of VB.Net is initializing:
Dim x As SomeType() = New SomeType(0) {}
What holds x variable? Is it an array? How can it be translated to C# for example?
I guess SomeType is probably an anonymous type, but still have no clue...
The line:
Dim x As SomeType() = New SomeType(0) {}
declares an array of SomeType objects, which can hold one instance of SomeType.
When declaring an array of objects the value that is passed into the constructor is the max index of the array. So this declaration is basically declaring an array with a length of 1. The {} portion of the line is where you could define the values that should be stored in the array. If you were to change SomeType to integer you could instantiate and fill your array like:
Dim intArray as Integer() = New Integer(0) {7}
and that would give the first instance stored in the intArray variable a value of 7.
SomeType is not an anonymous type. SomeType would be a class that would have to be defined somewhere in your app.
In C# I think the sytax would look like:
SomeType[] x = new SomeType[0];
I'm not exactly sure how you would accomplish the {} portion of the VB.NET line in C#.
It's simply declaring and initializing an array of a given type. In C# I think it would be, quite similarly:
SomeType[] x = new SomeType[0] { };
Is it an array?
Yes. VB uses () for arrays instead of C#'s [].
I guess SomeType is probably an anonymous type
No, it's a defined static type like any other.
I am in need of performing a volatile write on a variable that is an Enum type derived from Byte, but I am stucked.
This is my (example) code:
Public Class MyOwnClass
Friend Enum MyEnum As Byte
Val1
Val2
End Enum
Private MyEnumVar As MyEnum = MyEnum.Val1
Friend Sub SetMyEnumVar(ByVal value As MyEnum)
System.Threading.Volatile.Write(MyEnumVar, value) 'Error!
End Sub
End Class
Since Threading.Volatile.Write is not provided with a signature with those arguments I get this error
Error 1 Overload resolution failed because no accessible Write can be called without a narrowing conversion:
With the list of all the overloads of the method.
CTyping the first argument is not working, because CType returns a casted value of course not with the same reference as MyEnumVar where the method gets the first parameter abviously ByRef instead.
CObject that would return a reference is also not viable because the method also hasn't got the overload for an object type other than Write(Of T)(T, T) where Tmust be a class type.
So how can I accomplish my purpose?
Thanks.
You can use the Write(Of T) overload where T is the type of Enum.
System.Threading.Volatile.Write(Of [Enum])(MyEnumVar, value)
In order to return a value from a VB.NET function one can assign a value to the "Functions Name" or use "return value."
I sometimes see these inter-mixed in the same function. Personally, I prefer the return.
My question is, what is the internal difference, if any, between the two?
The difference is that they DO DIFFERENT THINGS!
'Return value' does 2 things:
1. It sets the function return value at that point
2. It immediately exits the function
No further code in the function executes!
'Functionname = value' does 1 thing:
1. It sets the function return value at that point
Other code in the function continues to execute
This enables additional logic to refine or override the function return value
Huge difference folks. Remember it's not all about state, it's also about flow.
Let's take a look... Oddly the "functionName =" generates less IL?
Code:
Public Function Test() As String
Test = "Test"
End Function
Public Function Test2() As String
Return "Test"
End Function
IL:
.method public static string Test() cil managed
{
.maxstack 1
.locals init (
[0] string Test)
L_0000: nop
L_0001: ldstr "Test"
L_0006: stloc.0
L_0007: ldloc.0
L_0008: ret
}
.method public static string Test2() cil managed
{
.maxstack 1
.locals init (
[0] string Test2)
L_0000: nop
L_0001: ldstr "Test"
L_0006: stloc.0
L_0007: br.s L_0009
L_0009: ldloc.0
L_000a: ret
}
There is probably no difference. IIRC, the compiler generated IL converts them both into Return statements unless there is additional usage of a _returnValue variable.
The readability of the FunctionName assignment is poor in my opinion, and an example of a bad VB6 habit. I prefer the _returnValue (NOT RETVAL) variable method also.
Doing the following is only provided for Visual Basic 6.0 developers to easily port code over:
Public Function MyFunction() As String
MyFunction = "Hello"
End Function
I would definitely not recommend keeping doing it if your project includes anyone who hasn't worked with Visual Basic 6.0, as this syntax will be confusing.
When Tools/Options/Text Editor/All Languages/Code Lens is activated, the Reference Count shows above each Sub, Function, or Property statement.
"Return Value" seems better than "assigning a value to the Functions Name". In the latter case, "Code Lens" produces an inflated Reference Count.
' Code Lens reports "0 references" here for Sub Rosa().
Public Sub Rosa()
Diagnostics.Debug.WriteLine(Test())
Diagnostics.Debug.WriteLine(Test2())
End Sub
' Code Lens reports "2 references" here for Function Test().
Public Function Test() As String
Test = "Test" ' Code Lens counts this as a reference.
End Function
' Code Lens reports "1 reference" here for Function Test2().
Public Function Test2() As String
Dim strTest2 as String = "Test"
Return strTest2 ' Code Lens does NOT count this as a reference.
End Function
99 times out of 100 I'll use "return value".
Every once in a while I'll have a function where the other type not only allows me to save a variable declaration, but do it in a way that actually significantly clarifies the function. Usually this happens when I would want to name the return value the same as the function anyway, and often these are recursive functions; something about that construct lends it to the implicit return variable. However, that scenario is extremely rare. I don't know if I have any functions using implicit return variables at all in my current project.
Having read that the Return Value syntax was the One True .NET Way Of Doing Things I thought "OK, we'll do it that way then". Then I wrote a function which I knew, hand on heart KNEW, returned either a value from a Return statement or alternatively an Exception under all circumstances, and still got a compiler warning that the function "doesn't return a value on all paths".
Thankfully I came across the Stack Overflow question How can I make this function not generate a “doesn't return a value on all paths” warning? which explained why; adding a default value assignment to the procedure name at the head of the function prevented the warning in my case as well.
Consequently, even though I'll continue to use the Return Value syntax simply for the sake of syntax consistency, I'll also be assigning a default value to the function name just to prevent the possibility of cluttering up the compile process with bogus warnings.
its quite handy when working with 3rd party factories(_hsf), you can avoid declaring return variables
Public Function CreateExtremum(iShape As INFITF.Reference, iDir1 As HybridShapeTypeLib.HybridShapeDirection, iSide1 As Integer, iDir2 As HybridShapeTypeLib.HybridShapeDirection, iSide2 As Integer, iDir3 As HybridShapeTypeLib.HybridShapeDirection, iSide3 As Integer) As HybridShapeTypeLib.HybridShapeExtremum
CreateExtremum = _hsf.AddNewExtremum(iShape, iDir1, iSide1)
CreateExtremum.Direction2 = iDir2
CreateExtremum.ExtremumType2 = iSide2
CreateExtremum.Direction3 = iDir3
CreateExtremum.ExtremumType3 = iSide3
CreateExtremum.Compute()
End Function