#### Directed Weighted Graph Via Adjacency Matrix

```using System;
using System.Collections.Generic;

namespace DataStructures.Graph;

/// <summary>
///     Implementation of the directed weighted graph via adjacency matrix.
/// </summary>
/// <typeparam name="T">Generic Type.</typeparam>
public class DirectedWeightedGraph<T> : IDirectedWeightedGraph<T>
{
/// <summary>
///     Capacity of the graph, indicates the maximum amount of vertices.
/// </summary>

/// <summary>
///     Adjacency matrix which reflects the edges between vertices and their weight.
///     Zero value indicates no edge between two vertices.
/// </summary>

/// <summary>
///     Initializes a new instance of the <see cref="DirectedWeightedGraph{T}"/> class.
/// </summary>
/// <param name="capacity">Capacity of the graph, indicates the maximum amount of vertices.</param>
public DirectedWeightedGraph(int capacity)
{
ThrowIfNegativeCapacity(capacity);

this.capacity = capacity;
Vertices = new Vertex<T>[capacity];
Count = 0;
}

/// <summary>
///     Gets list of vertices of the graph.
/// </summary>
public Vertex<T>?[] Vertices { get; private set; }

/// <summary>
///     Gets current amount of vertices in the graph.
/// </summary>
public int Count { get; private set; }

/// <summary>
///     Adds new vertex to the graph.
/// </summary>
/// <param name="data">Data of the vertex.</param>
/// <returns>Reference to created vertex.</returns>
{
ThrowIfOverflow();
var vertex = new Vertex<T>(data, Count, this);
Vertices[Count] = vertex;
Count++;
return vertex;
}

/// <summary>
///     Creates an edge between two vertices of the graph.
/// </summary>
/// <param name="startVertex">Vertex, edge starts at.</param>
/// <param name="endVertex">Vertex, edge ends at.</param>
/// <param name="weight">Double weight of an edge.</param>
public void AddEdge(Vertex<T> startVertex, Vertex<T> endVertex, double weight)
{
ThrowIfVertexNotInGraph(startVertex);
ThrowIfVertexNotInGraph(endVertex);

ThrowIfWeightZero(weight);

ThrowIfEdgeExists(currentEdgeWeight);

}

/// <summary>
///     Removes vertex from the graph.
/// </summary>
/// <param name="vertex">Vertex to be removed.</param>
public void RemoveVertex(Vertex<T> vertex)
{
ThrowIfVertexNotInGraph(vertex);

int indexToRemove = vertex.Index;
vertex.Index = -1;
vertex.SetGraphNull();

// Update the vertex array and the index of vertices.
for (int i = indexToRemove; i < Count - 1; i++)
{
Vertices[i] = Vertices[i + 1];
Vertices[i] !.Index = i;
}

Vertices[Count - 1] = null;

// Update adjacency matrix to remove the row and column of the removed vertex.
for (int i = 0; i < Count; i++)
{
for (int j = 0; j < Count; j++)
{
if (i < indexToRemove && j < indexToRemove)
{
continue;
}
else if (i < indexToRemove && j >= indexToRemove && j < Count - 1)
{
}
else if (i >= indexToRemove && i < Count - 1 && j < indexToRemove)
{
}
else if (i >= indexToRemove && i < Count - 1 && j >= indexToRemove && j < Count - 1)
{
}
else if (i == Count - 1 || j == Count - 1)
{
}
else
{
throw new InvalidOperationException();
}
}
}

Count--;
}

/// <summary>
///     Removes edge between two vertices.
/// </summary>
/// <param name="startVertex">Vertex, edge starts at.</param>
/// <param name="endVertex">Vertex, edge ends at.</param>
public void RemoveEdge(Vertex<T> startVertex, Vertex<T> endVertex)
{
ThrowIfVertexNotInGraph(startVertex);
ThrowIfVertexNotInGraph(endVertex);
}

/// <summary>
///     Gets a neighbors of particular vertex.
/// </summary>
/// <param name="vertex">Vertex, method gets list of neighbors for.</param>
/// <returns>Collection of the neighbors of particular vertex.</returns>
public IEnumerable<Vertex<T>?> GetNeighbors(Vertex<T> vertex)
{
ThrowIfVertexNotInGraph(vertex);

for (var i = 0; i < Count; i++)
{
{
yield return Vertices[i];
}
}
}

/// <summary>
///     Returns true, if there is an edge between two vertices.
/// </summary>
/// <param name="startVertex">Vertex, edge starts at.</param>
/// <param name="endVertex">Vertex, edge ends at.</param>
/// <returns>True if edge exists, otherwise false.</returns>
public bool AreAdjacent(Vertex<T> startVertex, Vertex<T> endVertex)
{
ThrowIfVertexNotInGraph(startVertex);
ThrowIfVertexNotInGraph(endVertex);

}

/// <summary>
/// Return the distance between two vertices in the graph.
/// </summary>
/// <param name="startVertex">first vertex in edge.</param>
/// <param name="endVertex">secnod vertex in edge.</param>
/// <returns>distance between the two.</returns>
public double AdjacentDistance(Vertex<T> startVertex, Vertex<T> endVertex)
{
{
}

return 0;
}

private static void ThrowIfNegativeCapacity(int capacity)
{
if (capacity < 0)
{
throw new InvalidOperationException("Graph capacity should always be a non-negative integer.");
}
}

private static void ThrowIfWeightZero(double weight)
{
if (weight.Equals(0.0d))
{
throw new InvalidOperationException("Edge weight cannot be zero.");
}
}

private static void ThrowIfEdgeExists(double currentEdgeWeight)
{
if (!currentEdgeWeight.Equals(0.0d))
{
throw new InvalidOperationException(\$"Vertex already exists: {currentEdgeWeight}");
}
}

private void ThrowIfOverflow()
{
if (Count == capacity)
{
throw new InvalidOperationException("Graph overflow.");
}
}

private void ThrowIfVertexNotInGraph(Vertex<T> vertex)
{
if (vertex.Graph != this)
{
throw new InvalidOperationException(\$"Vertex does not belong to graph: {vertex}.");
}
}
}
```