Constructors calling other constructors in vb.net a la c# - vb.net

In c# you can have
public class Foo
{
public Foo(string name)
{
//do something
}
public Foo(string name, int bar) : this(name)
{
//do something
}
}
Is there a VB.Net equivalent?

It looks similar to Java in this respect:
Public Class Foo
Public Sub New(name As String)
' Do something '
End Sub
Public Sub New(name As String, bar As Integer)
Me.New(name)
' Do something '
End Sub
End Class
Note that you have to use MyBase.New(...) in case you want to call a constructor of a base class. See also VB.NET OOP Part2 – Understanding Constructors.

Related

How works extensions method in VB.net with an interface as a object

I am struggling with an extension method in VB.NET, but I can't find why I can't implement this (I came from C# and I still having issues like this between language specification and how the language works, sorry if this question is too newbie):
namespace FakeBusiness.BusinessInterface
{
public interface IBusiness
{
int Id { get; set; }
string Name { get; set; }
}
}
namespace FakeBusiness.SharedExtensions
{
using FakeBusiness.BusinessInterface;
public static class ExtensionsMethods
{
public static bool IsEmpty(this IBusiness theObject)
{
return theObject != null && theObject.Id != 0;
}
}
}
namespace FakeBusiness.BusinessLogic
{
using FakeBusiness.BusinessInterface;
using FakeBusiness.SharedExtensions;
public class Business : IBusiness
{
public int Id { get; set; }
public String Name { get; set; }
}
public static class Program
{
public static void Main(string[] args)
{
IBusiness obj = new Business();
Console.WriteLine($"The object is: {(obj.IsEmpty() ? "empty" : "not empty")}");
}
}
}
And I want to achieve the same logic but for a reason VB.NET says 'Cannot resolve the symbol' even if I import explicitly the namespace from the extension method:
Namespace FakeBusiness.SharedExtensions {
<Extension()>
Public Function IsBusinessObjectEmtpy(ByVal business As IBusiness) As Boolean
Return (business IsNot Nothing AndAlso business.Id = 0)
End Function
End Namespace
Namespace FakeBusiness.BusinessLogic
Public Class BusinessObject : Implements IBusiness
Property Id As Integer Implements IBusiness.Id
Property Name As String Implements IBusiness.Name
Public Sub New()
End Sub
End Class
Public Interface IBusiness
Property Id As Integer
Property Name As String
End Interface
Public Class FakeBusiness.SomeLogic
Public Sub SomeLogic()
Dim newObject = New BusinessObject()
If newObject.IsBusinessObjectEmpty() Then
' Do something...
End If
End Sub
End Class
End Namespace
Also I read that a possible solution is to use the instructions Option Strict On/Off and also Option Infer On/Off.
I tried every possible combination between these pair of compiler instructions but it didn't work.
Anyone knows how to fix this issue with an extension method?
Another possible solution is to put the same method into a base class and implement with an interface, but I want to achieve this in this way
because it will be useful to use in every class if I use a TypeParameter in the extension method.
Any suggestion?
In a Console Application project with a root namespace of FakeBusiness, the following is the direct equivalent of that C# code:
Namespace BusinessInterface
Public Interface IBusiness
Property Id As Integer
Property Name As String
End Interface
End Namespace
Imports System.Runtime.CompilerServices
Imports FakeBusiness.BusinessInterface
Namespace SharedExtensions
Public Module ExtensionMethods
<Extension>
Public Function IsEmpty(theObject As IBusiness) As Boolean
Return theObject IsNot Nothing AndAlso theObject.Id <> 0
End Function
End Module
End Namespace
Imports FakeBusiness.BusinessInterface
Imports FakeBusiness.SharedExtensions
Namespace BusinessLogic
Public Class Business
Implements IBusiness
Public Property Id As Integer Implements IBusiness.Id
Public Property Name As String Implements IBusiness.Name
End Class
Module Program
Sub Main(args As String())
Dim obj As IBusiness = New Business()
Console.WriteLine($"The object is: {If(obj.IsEmpty(), "empty", "Not empty")}")
End Sub
End Module
End Namespace

Is it possible to implement extension methods on generic interfaced collections in VB.NET?

I can't manage to write a VB.NET extension method which can be called from an object of type ListOfTests in the below solution.
I can write the extension method in C# using generic type constraints.
Here's some test code I've writen to demonstrate the problem which I have encountered in a much larger existing VB.NET solution.
The extension method in question here is FilterByIDs, which is just an abritrary example I chose.
Working C# solution:
using System;
using System.Collections.Generic;
using System.Linq;
static class TestApp
{
public static void Main()
{
var objTest = new ListOfTests
{
new Test {Id = 1}, new Test {Id = 2}, new Test {Id = 3}
};
objTest.FilterByIDs(new [] {3});
// Prints "3" only - Extension method works
objTest.ForEach(x => Console.WriteLine(x.Id));
}
}
public static class Extensions
{
public static void FilterByIDs<T, TID>(this List<T> target, IEnumerable<TID> objIDs) where T : ITest<TID>
{
target.RemoveAll(x => !objIDs.Contains(x.Id));
}
}
public class ListOfTests : List<Test>
{}
public class Test : ITest<int>
{
public int Id { get; set; }
}
public interface ITest<TID>
{
TID Id { get; }
}
My attempt at writing this in VB.NET (Does not build):
Imports System.Runtime.CompilerServices
Class TestApp
Public Shared Sub Main()
Dim objTest As New ListOfTests()
objTest.Add(New Test() With { .ID = 1})
objTest.Add(New Test() With { .ID = 2})
objTest.Add(New Test() With { .ID = 3})
objTest.FilterByIDs({3})
objTest.ForEach(Sub(x) Console.WriteLine(x.ID))
End Sub
End Class
Public Module Extensions
<Extension>
Public Sub FilterByIDs(Of T As ITest(Of TID), TID)(target As List(Of T), objIDs As IEnumerable(Of TID))
target.RemoveAll(Function(x) Not objIDs.Contains(x.Id))
End Sub
End Module
Public Class ListOfTests
Inherits List(Of Test)
End Class
Public Class Test
Implements ITest(Of Integer)
Public Property ID As Integer Implements ITest(Of Integer).ID
End Class
Public Interface ITest (Of T)
Property ID As T
End Interface
Build error from the VB.NET solution is
" TestApp.vb(18, 16): [BC36561] Extension method 'FilterByIDs' has type constraints that can never be satisfied."
Is it possible to write this in VB.NET?
Not the same elegance and compile safety, but working:
<Extension>
Public Module Extensions
<Extension>
Public Sub FilterByIDs(Of T)(target As IList, objIDs As IEnumerable(Of T))
If (target Is Nothing) Then Throw New NullReferenceException() 'To simulate instance method behavior
For i As Int32 = target.Count - 1 To 0 Step -1
Dim myTest As ITest(Of T) = TryCast(target(i), ITest(Of T))
If (myTest Is Nothing) Then
target.RemoveAt(i)
Else
If (Not objIDs.Contains(myTest.ID)) Then target.RemoveAt(i)
End If
Next
End Sub
End Module

The equivalent of c# virtual in vb when calling method *within* base class

I understand how to use VB's Overridable and Overrides, to get similar functionality to c#'s virtual when calling methods of a class. However, consider the c# console code below, which calls an overridden method from within the class itself:
class Program {
static void Main(string[] args) {
new test();
new test2();
Console.ReadKey();
}
}
public class test {
public test() {
hello();
}
public virtual void hello() {
Console.WriteLine("hello from base method");
}
}
class test2 : test {
public override void hello() {
Console.WriteLine("hello from overridden method");
}
}
The result I get, predictably, in c# is:
hello from base method
hello from overridden method
The problem is, I can't work out how to duplicate this functionality in VB.NET. Keep in mind here that hello() is being called from within the base class code, which runs the overridden method. That is what I can't seem to accomplish in VB.
No matter what I try in VB, the base class's hello() is always called, not the overridden hello().
Class Test:
Public Class Test
Public Sub New()
Hello()
End Sub
Public Overridable Sub Hello()
Console.WriteLine("hello from base method")
End Sub
End Class
Class Test2:
Public Class Test2
Inherits Test
Public Overrides Sub Hello()
Console.WriteLine("hello from overridden method")
End Sub
End Class
Sub Main:
Sub Main()
Dim x As New Test
Dim y As New Test2
End Sub

VB.NET: Use property as delegate function

I have got a problem with converting an example from C# to VB.NET.
The C# example has the following structure.
First there is a public delegate.
public delegate void CustomEventHandler(object sender , EventArgs e);
This delegate is connected to an property of an interface.
public interface ICustom {
CustomEventHandler MyProperty { get; set; }
}
Finally I have got a class with a function containing the interface as parameter. This property is called with the parameters like a function.
public class Test {
public void MySub(ICustom custom) {
custom.MyProperty(this, new EventArgs()); }
}
I can convert this code except for the use of the property. My VB.NET code looks like the following:
Public Delegate Sub CustomEventHandler(ByVal sender As Object, ByVal e As EventArgs)
Public Interface ICustom
Property MyProperty As CustomEventHandler
End Interface
Public Class Test
Public Sub MySub(ByVal custom As ICustom)
... How can I add here the event OnEvent to the event custom.MyEvent? ...
End Sub
End Class
Is it possible to convert this or is there another way necessary.
Thanks for any response.
For firing events in VB.NET you have to use RaiseEvent
http://msdn.microsoft.com/en-us/library/edzehd2t.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

Private or Protected Set for a MustOverride Property

I'd like to have a Private or Protected "Setter" for a property that also happens to be an abstract (MustOverride). I'm porting some code from C# to VB and in C# this is pretty straight forward. In VB not so much (for me anyway).
Some code...
In C#...
public abstract class BaseClassWithAnAbstractProperty
{
public abstract int AnAbstractIntegerProperty { get; protected set; }
}
public class Foo : BaseClassWithAnAbstractProperty
{
private int _anAbstractIntegerPropertyField = 0;
public override int AnAbstractIntegerProperty
{
get { return _anAbstractIntegerPropertyField; }
protected set { _anAbstractIntegerPropertyField = value; }
}
}
In VB...
Public MustInherit Class BaseClassWithAnAbstractProperty
Public MustOverride Property AnAbstractIntegerProperty() As Integer
End Class
Public Class Foo
Inherits BaseClassWithAnAbstractProperty
Private _anAbstractIntegerPropertyField As Integer
Public Overrides Property AnAbstractIntegerProperty As Integer
Get
Return _anAbstractIntegerPropertyField
End Get
Protected Set(ByVal value As Integer)
_anAbstractIntegerPropertyField = value
End Set
End Property
End Class
The issue seems to be the inability to flesh-out the Get/Set specifics in the declaration.
Am I chasing a ghost?
For the record, the closest VB translation would give you:
Public MustInherit Class BaseClassWithAnAbstractProperty
Public ReadOnly MustOverride Property AnAbstractIntegerProperty() As Integer
End Class
This might work, but as I found out, VB doesn't support this for Interfaces, at least