LastExceed
LastExceed
CC#
Created by LastExceed on 1/21/2025 in #help
✅ When should/shouldn't I split off code into a separate lib project?
I am cleaning up a massive legacy codebase at work. At the time my company acquired it, it consisted of 71 projects (spread across 6 solutions, which we have already merged into 1 for easier dependency management). 11 Of these are executables, the rest are libs. Some of these libs are definitely unnecessary (e.g. only containing 1 class that barely even warrants its own namespace), others are definitely necessary (e.g. needed by multiple executables). Likewise, there is a huge "common" project that is referenced everywhere because it contains all sorts of things, and dependants usually only need a small subset, so it seems reasonable to split it up to reduce coupling. So far we have brought it down to 1 solution with 31 projects, but I'm reaching a point where I'm no longer confident in making these decisions solely by gut feeling, and I'd much prefer having some clear principles to follow, because I've come to realize that splitting based on what's-needed-where can be done with endless granularity, and I don't know where to draw the line. 1. What are some general rules of thumb to follow? 2. How does project splitting affect * IDE performance * compile time * binary size * runtime performance? 3. Is an executable depending on another executable (as opposed to extracting a shared lib project) even a fundamentally bad thing?
76 replies
CC#
Created by LastExceed on 12/11/2024 in #help
do lambda params support any form of deconstruction syntax?
i would have expected one of these to work:
new[] { (1, 2) }
.Select((a, b) => a + b);

new[] { new { a = 1, b = 2 } }
.Select((a, b) => a + b);
new[] { (1, 2) }
.Select((a, b) => a + b);

new[] { new { a = 1, b = 2 } }
.Select((a, b) => a + b);
but unfortunately they dont. is anything like this possible in lambda params at all?
4 replies
CC#
Created by LastExceed on 5/29/2024 in #help
how do transitive dependencies work?
here is a project dependency diagram generated in rider: https://i.imgur.com/yCfVEuX.png why do only 3 other project projects have a transitive dependency on Contenit.Interfaces (direct dependency of LVS_Common) even though all projects in the solution depend on LVS_Common in some form?
1 replies
CC#
Created by LastExceed on 5/2/2024 in #help
✅ how can i let an interface implement a function of a super-interface, instead of shadowing it?
public class MyClass : IOne;

public interface IOne : ITwo
{
public void Foo()
{
Console.WriteLine();
}
}

public interface ITwo
{
public void Foo();
}
public class MyClass : IOne;

public interface IOne : ITwo
{
public void Foo()
{
Console.WriteLine();
}
}

public interface ITwo
{
public void Foo();
}
this doesnt compile, because IOne.Foo is considered a separate function that shadows ITwo.Foo. how do i tell IOne to provide a default implementation for ITwo.Foo instead of shadowing it?
24 replies
CC#
Created by LastExceed on 6/2/2023 in #help
❔ null warning while indexing (rather than accessing) null-agnostic type?
first, lets look at a scenario where everything behaves as expected:
string[]? GetList() => throw new NotImplementedException();

var myList = GetList();
string a = myList.ElementAt(0); //null warning while accessing `myList` - as expected
string b = myList[0]; //same thing here - as expected
string c = myList[0]!; //this doesn't change anything, because its not the indexer but the variable that is nullable - as expected
string c = myList![0]; //this successfully suppresses the warning - as expected
string[]? GetList() => throw new NotImplementedException();

var myList = GetList();
string a = myList.ElementAt(0); //null warning while accessing `myList` - as expected
string b = myList[0]; //same thing here - as expected
string c = myList[0]!; //this doesn't change anything, because its not the indexer but the variable that is nullable - as expected
string c = myList![0]; //this successfully suppresses the warning - as expected
but if we move GetList to another project that doesn't use nullables:
#nullable disable //basically any project up until C# 7.3
namespace Foo;

public static class Stuff
{
public static string[] GetList() => throw new NotImplementedException();
}
#nullable disable //basically any project up until C# 7.3
namespace Foo;

public static class Stuff
{
public static string[] GetList() => throw new NotImplementedException();
}
now we get the following behaviour:
using Foo;

var myList = Stuff.GetList();
string a = myList.ElementAt(0); //no warning at all, despite having configured interpretation of null-agnostic types to be pessimistic - weird but whatever
string b = myList[0]; //here we DO get a null warning (dunno why this makes a difference), however its not while accessing the variable (where i would expect one), but while INDEXING it - wtf?
string c = myList[0]!; //this suppresses that warning - ok, but why was it there in the first place?
string d = myList![0]; //this doesn't.
using Foo;

var myList = Stuff.GetList();
string a = myList.ElementAt(0); //no warning at all, despite having configured interpretation of null-agnostic types to be pessimistic - weird but whatever
string b = myList[0]; //here we DO get a null warning (dunno why this makes a difference), however its not while accessing the variable (where i would expect one), but while INDEXING it - wtf?
string c = myList[0]!; //this suppresses that warning - ok, but why was it there in the first place?
string d = myList![0]; //this doesn't.
can someone explain?
38 replies