Should System be explicitly imported in a Xamarin.Android class file? - c#

I'm pruning out unnecessary using directives, and am not sure if I should leave
using System;
in all my files or not?
In a Xamarin.Android Visual Studio class file, this directive
imports the namespace defined in
...\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0\System.dll
However, I have many files that are not explicitly using any types from there (which can be indicated by the faded/grayed syntax highlighting). However, it is my understanding that .NET primitives are aliases that the compiler substitutes for types within the System namespace (int <=> System.Int32), so I'm not sure if this could potentially cause any issues. The compiler never throws any kind of ambiguity error if omitted (between .NET System and Xamarin System), and my testing so far hasn't resulted in any issues.

You ask that question because you have a misunderstanding between the using directive and referenced assemblies.
using does not reference any assembly.
The References added to your project do (s. the "References" node in the Solution Explorer, or "Dependencies" in .NET Core projects), hence their name, References.
using only allows you to shortcut using namespaces or types available in the previously separately referenced assemblies in your code, e.g. writing Console.WriteLine() instead of System.Console.WriteLine().
You may ask why this differentation has been made in the first case. Well, one issue would be that if you had two assemblies defining types with the same name (let's say, some XBox related assembly also providing a Console type) and you would also reference the assemblies with the using directive as you were thinking, there'd be no way to differ between System.Console or XBox.Console in code, as there are now two Console types accessible at the "same time".
To come back to reality, you can remove any using directives which are grayed out with absolutely no impact on how your application behaves as the references to the assemblies will still stay intact (nothing in the "References" node in your Solution Explorer will have changed), and so your application will still be able to access the types defined in System - just you won't be able to use them like Int32 instead of System.Int32 for example.
Now the joke about the primitive types is that C# provides keywords to shortcut those types like Int32 at any time (no matter if you have using System; on top of your file or not) by writing simply int, or bool for System.Boolean, and so on. That's the reason why your directive is grayed out, because you used those primitive types (if at all) through their keyword. Replace one int with the actual type name Int32 and you'll see the directive not being grayed out anymore.

If it's greyed out then yup, delete it. You don't need it for primitive types, only for objects inside that namespace such as DateTime or Guid.
Using directives have nothing to do with what assemblies are in use, only to help the compiler resolve types that are not qualified with namespaces. Any greyed out using can be deleted.

Related

C# namespaces: Calling a method in two identical namespaces with same name

I'm trying to understand C# namespaces. Suppose two namespaces exist with the same name and they have identical contents, i.e. all classes and methods also have identical names. How can the compiler distinguish between the two if I try to call a method, e.g. MyMethod in class MyClass in namespace MyNamespace? It's not likely a real-world scenario, but I find the information useful for understanding purposes.
Second question: When I dot on a namespace, e.g. System, I get a set of related namespaces like System.Configuration etc., but when I go to Microsoft's documentation I cannot find any namespace named Configuration contained in System namespace. Why is that? I can of course find the namespace if I look for System.Configuration, but I don't understand why the System.Configuration namespace is not nested inside the System namespace.
If you have two types that have the same name and same number of type parameters, and exist in the same namespace, then the assemblies that they are in must be different.
If your project references the assembly that one type is in, but not the other, then you will obviously only be able to refer to the type that is from the assembly that you referenced. If your project references both assemblies, then there will be a compiler error, like this. To fix it, you can use an extern alias.
Not being able to find System.Configuration in this page is merely due to how Microsoft organises their documentation. They have decided to list all the namespaces out here, rather than display a hierarchy. Note that System.Configuration is part of the .NET Platform Extensions, not plain old .NET, so you have to choose that in the dropdown.

The type "Action<T1,T2,T3>" exists in 2 DLLs, how do I specify which one to use or just avoid one?

I making an app with Unity3D and using this socket.io plugin but when I'm using Unity 2019.1 I get the following errors:
/.../Unity.app/Contents/Resources/PackageManager/BuiltInPackages/com.unity.timeline/Runtime/TrackAsset.cs(17,38): error CS0433: The type 'Action<T1, T2, T3>' exists in both 'WebSocket4Net, Version=0.14.1.0, Culture=neutral, PublicKeyToken=eb4e154b696bf72a' and 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
And that is because Action is defined both in WebSocket4Net, which I use, even tho I'm not using that specific reference and in System, which again, I'm not using.
System.Action is being used by Unity, while the one in WebSocket4Net is used to make JSON from the library Newtonsoft.Json, which I'm not using but is strictly linked to the WebSocket4Net and can't be removed.
I tried specifying System.Action whenever Unity uses that, but that's no solution, the error is still there.
Tried removing WebSocket4Net and this removes that error, but create a new error:
'HashSet<GameObject>' does not contain a definition for 'Contains' and no accessible extension method 'Contains' accepting a first argument of type 'HashSet<GameObject>' could be found (are you missing a using directive or an assembly reference?)
when HashSet should have this method by default.
Tried removing all 3 DLLs from the plugins folder in order to avoid having these issues, but then I won't have sockets,
Is there any way to fix this? I don't want to dive into the libraries to bugfix that, but is there any other solution?
I'm assuming that you mean "in the same full namespace"; if that assumption is incorrect and they're simply in different namespaces, then: just use full name qualification, i.e. global::Foo.Bar.Whatever instead of just Whatever. You can also add a "using alias" on a per-file basis for convenience, i.e.
using Mwahaha = global::Foo.Bar.Whatever;
and now you can use Mwahaha as an alias every time you mean global::Foo.Bar.Whatever in that file.
So; going back to my assumption that you mean "in the same full namespace":
Conflicting full type names is a major pain, and how to fix it depends a lot on your build chain. The simplest fix here is to encourage library authors not to do this, perhaps using [assembly:TypeForwardedTo(...)] if the thing they added for compatibility is now available in an "official" location (i.e. if library A adds a type, then later the "official" version is added somewhere, library A can delete their version of it, and add [assembly:TypeForwardedTo(typeof(TheType))] where TheType is now from the "official" library, and everything should work correctly without even breaking callers, if the types are truly compatible; callers expecting the type in A will be redirected to the official version automatically without even needing to be recompiled).
Otherwise...
The compiler supports this, but via something called "extern aliases". When you reference any dll, by default it gets the global namespace alias. However, specifically for this scenario, you can override that and tell it which namespace to use on a per-dll basis. So you could say that everything from a.dll goes into global (i.e. the default), but everything from b.dll goes into the blah namespace alias. You then need to use extern alias in every single file where you want to access things from blah (i.e. from b.dll). This gets annoying very quickly, but works. The short version would be:
extern alias blah;
and then use blah::Foo.Bar.Whatever in every location in that file to refer to Foo.Bar.Whatever from b.dll; or combined with "using alias":
extern alias blah;
using Mwahaha = blah::Foo.Bar.Whatever;
and now Mwahaha refers to Foo.Bar.Whatever from b.dll but only in that file.
The article above covers how to specify the per-dll aliases with csc, but in reality almost nobody uses csc directly.
For old-style csproj in Visual Studio, the alias can be specified in the properties window of the reference. For new-style csproj, you have to use an ugly hack:
<Target Name="ChangeAliasesOfReferences"
BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'b'"><!-- the dll -->
<Aliases>blah</Aliases><!-- the namespace aliases -->
</ReferencePath>
</ItemGroup>
</Target>
As for how to do this with the unity build chain: your guess is as good as mine.

why we give reference to the other projects?

When looking at a solution with multiple projects:
1) Why do we add a reference to the other project? Can't we just use inheritance?
2) After we add the reference by using Visual Studio, why do we have to add the project to the namespace system? For example: using myReferenceProject; I thought that the IDE would do that.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using myReferenceProject;
using System.Data.SqlClient;
using System.Data;
1) why we give reference to the other project? cant we just use inheritance???
They're two completely different concepts.
Adding a reference to another assembly basically says, "I want to be able to use some of this code. Please make the compiler aware that this code exists, and optionally copy it into the output directory so that it's present at execution time too."
How would you expect to use inheritance to create a class derived from some type if the compiler has no knowledge of that type?
2) after we give the reference by using the visual studio IDE why we have to add the project to the namespace system???
Because assemblies and namespaces are different concepts too. A using directive simply says to the compiler "When I refer to type Foo within my code, look in these namespaces to try to resolve it." That type could come from any of the assemblies you've referenced.
It's really important that you understand the difference between assemblies and namespaces. Even though they're often named similarly (Foo.Bar.dll often provides types in the namespace Foo.Bar) they're conceptually different.
The project is a self sufficent compilable unit, that has to compile into the valid assembly file. That's why you need esplicitly specifiy which referencies every project needs in order to be able to compile separately from others.
There is no any inheritance concept on projects level.
1) why we give reference to the other project? cant we just use inheritance?
This question makes no sense. What does inheritance have to do with project references. Can you elaborate?
2) after we give the reference by using the visual studio IDE why we have to add the project to the namespace system?
Because there's an inherent difference between an assembly referencing another assembly (which is what happens when you add a reference to the project) and the language knowing where to find a class which is what happens when you use the using directive in a file.
For example, suppose you create a class in your project called TextBox. Then in another file you want to use that class. How would the language know whether you are referring to your custom TextBox class or another one in a referenced assembly? The answer to that question is namespaces. By fully-qualifying the class name with its namespaces, you tell the compiler which class you're using.
The using directive is a way to specifying the namespace once per file instead of every time you use the class (or other classes in that namespace). So if you need to reference your TextBox class multiple times within a single file, you wouldn't want to have to write this every time:
MyCodebase.MyAssembly.MyNamespace.MyOtherNamespace.SomethingElse.TextBox
Instead, you include a using directive of the entire namespace, so you only have to write this:
TextBox

How to overcome same type in two namespaces, System.Linq.Expressions.Expression<TDelegate>?

I am defining some Expression variables in my app and need to have a reference to Microsoft.Scripting.Core. That assembly includes the same namespace as the System.Core assembly from the main .Net framework.
I want to use the defintions from the System.Core assembly as it's stable whereas the Microsoft.Scripting.Core is alpha.
How do I tell my app to preference the System.Linq.Expressions namespace in System.Core instead of Microsoft.Scripting.Core but still be able to keep the reference to it?
As Marc says, it's not terribly nice - but extern aliases are the way to go.
In the "References" part of solution explorer, select the System.Core assembly, go to properties. Change the "Aliases" property to include "syscore", e.g.
Aliases: global,syscore
Then at the top of any file where you want to use System.Linq.Expressions, type:
extern alias syscore;
using syscore::System.Linq.Expressions;
It's ugly, but at least it's possible :)
As a caveat, I've seen some problems when it comes to extension methods and extern aliases, as described in this question.
If they are the same namespace but different assemblies, then you may need to look at "extern alias", but that gets very messy very quickly.
If they are different namespaces, then simply use different using directives; you can also use using aliasing. However, lambdas will always (AFAIK) use the original namespace.

Finding references in Visual Studio

I'm using Visual Studio and COM with C# for the first time and there's something I don't quite understand about the 'references'. How do you know what to reference with a given 'using something.something'? The .Net references seem fairly simple, but COM is less obvious. I'm running Visual Studio 2005 and have the latest VSTO installed, but for the life of me, I can't figure out what I need to reference to satisfy:
using Microsoft.VisualStudio.Tools.Applications.Runtime;
There are a few Microsoft.VisualStudio things in the .Net tab, but none that continue with .Tools or anything like it. I feel like I'm missing a key concept here.
There are two issues here -
First, a reference doesn't necessarily correspond to a namespace. A single reference can contain multiple namespaces, and a single namespace can be shared by multiple assemblies which would need to be referenced. Needing to include a reference allows you to use specific types, not entire namespaces.
Second, this is something you'll need to know in advance. If you're using Microsoft's classes, such as the ones in the namespace you listed, MSDN can be a great help.
For example, take Microsoft.VisualStudio.Tools.Applications.Runtime.ServerDocument
If you look at the MSDN page for this class (in that namespace), near the top it includes:
Namespace: Microsoft.VisualStudio.Tools.Applications.Runtime
Assembly: Microsoft.VisualStudio.Tools.Applications.Runtime (in microsoft.visualstudio.tools.applications.runtime.dll)
This specifically tells you which assembly is required.
That reference is part of the Visual Studio SDK. I am currently using VS 2008, but the assemblies should be the same for VS 2005. The link for the SDK is here.
Going the other way is pretty easy. If you're given a reference, you can open that reference in the object browser to see what namespaces it contains, and from that, determine what usings to add. Its not trivial to determine what to reference for a given using, as there's no guarantee that there exists exactly one DLL for each namespace. How is it that you arrived at a
using Microsoft.VisualStudio.Tools.Applications.Runtime;
Without knowing what to reference? If its a code sample somewhere, they ought to mention what the external references and dependencies of the project are.

Categories

Resources